TypeScript — a beginner’s primer

Rick Glascock
6 min readOct 18, 2020
Photo by Peter Pryharski on Unsplash

This blog should serve as an introduction to what TypeScript is (and isn’t) as well as basic instructions for getting TypeScript set up and running in VSCode allowing you to further experiment on your own.

JavaScript can be notoriously loose with its interpretation of code. Numbers are coerced to strings. Strings are coerced to numbers. You can write a function that multiplies two numbers, and then pass a string as one of the arguments without an error.

3 * '3' // 9
3 + '3' // '33'
3 + 3 + '3' // '63'
function multiply(a, b){
console.log(a*b)
}
multiply(4, 'bob') //NaN

The wild west nature of JavaScript can be liberating, but can also lead to frustratingly hard to diagnose bugs in your code.

Enter TypeScript.

TypeScript tames JavaScript. It adds a layer of configurable checks on your JS code, adding warnings and errors that can help you maintain type continuity and avoid errors down the road. It brings JS closer to a strictly typed language like Java.

How does TypeScript work? TypeScript is a Static Type Checker. TypeScript checks code for errors and inconsistencies before it’s run. Writing in TypeScript (TS) is just like writing JS, in fact TS is a superset of JS code with some extras that allow/encourage you to be more specific about your intentions. The code below is the same as the code above, but now we’ve typed our function parameters as numbers using TS syntax:
myVariable: number
Calling the function with a string results in TS throwing a warning (the warnings can be seen by hovering over the offending argument, ‘bob’).

//index.tsfunction multiply(a: number, b: number){
console.log(a*b);
}
multiply(4, 'bob')

Argument of type ‘string’ is not assignable to parameter of type ‘number’.ts(2345)

Notice that we’ve created the above code in a file with a .ts extension to differentiate TS code form JS code.

Browsers won’t understand the TS commands that fall outside of vanilla JS, so the TS file needs to eventually (or continuously, as we’ll see) be complied into a plain old vanilla JS file. This is the key — Once TS files are compiled into JS, the TS specific language is stripped out. If we don’t fix the problems in highlighted in TS, they will remain in our JS after compilation. Here’s the code above, after compiling the TS:

//index.jsfunction multiply(a, b) {
console.log(a * b);
}
multiply(4, 'bob');

TypeScript’s strategy — “You can do that if you want, but I wouldn’t recommend it”.

Getting Started

  • I’m using TS with VS Code.
  • Set up a new JS project folder with index.html and index.js.
  • You can open index.html in a browser window, or better yet use an extension like live-server to continuously update the browser with your updated index.js file.
  • From a terminal window in the project folder:
  • Make sure Node is installed (node -v to check) or install.
  • set up a package.json with npm config
  • install typescript globally npm install -g typescript
  • create an index.ts file in the directory

You’re now ready to go. Delete the index.js file. Add our function to index.ts:

function multiply(a, b) {
console.log(a * b);
}
multiply(4, 'bob');

If you hover over the parameters a or b you’ll see a TS hint telling that they are of type ‘any’. In TS any is a type that means just what it says, basically the way vanilla JS sees variables, anything goes.

Add : number (lowercase) after the two parameters. You’ve set the function’s parameters as type number.

//index.tsfunction multiply(a: number, b: number){
console.log(a*b);
}
multiply(4, 'bob')

You should see a warning (hover over ‘bob’) that string can’ t be used in a parameter set for a number. Change ‘bob’ to a number and the warning disappears!

So how do we compile the TS file. Simple — in a bash terminal, type

tsc index.ts

The file compiles, without errors and voila, there is an index.js in your folder that includes the code without the TS. You’ll also note that now, back in index.ts there’s a warning on the function call. Delete index.js and it will go away. The warning is due to having duplicate functions the same folders. A bit later you’ll learn how to store the compiled file in another folder.

Back in index.ts try passing ‘bob’ for one of the arguments again and then compile the code. You’ll see a nasty error in the console, but the mistyped code does compile into index.js resulting in a return of NaN.

Watch Mode

Obviously we don’t want to have to manually recompile our index.ts file every time we make a change. Fortunately TS provides a solution!

tsc index.ts --watch    //OR
tsc index.ts -w

In watch mode the TS file will watch for changes and automatically recompile to an updated JS file making the work flow much faster!

More Options — TSConfig

While watch mode is a big step, there are numerous other options for how the TS compiler does it’s job. These options can be configured by setting up a config file in the root of your project folder:

tsc --init

This will create a tsconfig.json file that offers lots of options. One big benefit is that you now don’t have to specify the specific .ts file you want compiled. Now all .ts files will be compiled when you run tsc -w resulting in separate .js files.

The tsconfig.json file allows us to do some house cleaning as well. Typically we might organize our project into two sub-folders: a src for the source files and a dist folder to keep the compiled .js files separate. Within tsconfig.json look for ‘Basic Options’ and find “outDir”. Uncomment this line and add the path to your dist folder to direct the compiled .js files into this directory. Try it out. After compiling the new index.js file should reside in the dist folder. Don’t forget to change the path of your <script src= /> in index.html to access the new file location.

TS and Objects

I’ve outlined the basics of how to use TypeScript with out spending much time on the core idea — types. TS offers a number a different types, some familiar to JS users and some new. While this article was not intended to delve too deeply into types, I will give a few examples to whet your appetite.

In TS we can assign a variable a type that is an array of strings. If we try to initiate the variable with an array of numbers TS complains:

const dogTricks: string[] = [‘flips’, ‘sit’, ‘speak’]; //Good Boy
const dogTricks: string[] = [1,2,3]; // Bad Boy

In TypeScript we can create a Type Alias that serves as a model for an object’s properties. This is very powerful as it keeps the references to that type of object pure throughout your code. Look at the following sequence:

//index.tstype Person = {
name: string;
age: number;
}
const myPerson: Person = {
name: 'Bob',
age: 23
}
const myPet = {
breed: 'Beagle',
age: 6
}
function sayHello(person: Person){
console.log(person.name + ' says hello.');
}
sayHello(myPerson);
sayHello(myPet);
  1. We make a type alias Person that requires a name (a string) and age property (a number)
  2. We type myPerson as a Person and assign its properties with correct types of values.
  3. We create another object (myDog with a breed instead of a name).
  4. We create a function whose argument is typed as our Person object.
  5. We call the function with myPerson and everything works as expected.
  6. We call the function with myPet and TS complains that we are not following the pattern we had originally designed (a Person).

This gives you a glimpse at the kind of control that TS can provide in much more complicated code. This same type of control becomes especially powerful in defining more complex classes. Now that you are set up, head over to the TypeScript Handbook to see what’s possible.

--

--

Rick Glascock

After years of teaching music in Austin, Shanghai and Yangon, I’m making a career change to my other passion, software development.