loading...

TypeScript Head First

harry profile image harry ・4 min read

In this post I'm going to go over some basic TypeScript magic, and how natural it feels coming from JavaScript. If you're like me and you've blown off learning TS because you don't have the time or think JS will suffice, just try it first. I promise it's awesome.

TypeScript is just JavaScript!

When using TypeScript, we can choose exactly how many TS features we want to use. This is great for implementing TypeScript in large projects over time, since we can use regular JS with TypeScript, even in the same files.

Let's finally just write some TypeScript

All you'll need is node and (while not 100% necessary but definitely 💯% useful, VSCode). To get started make a new directory and call it whatever you want. After that run sudo npm install typescript -g so we can just type in tsc FILE_NAME.js to transpile our .ts files
Yes there's Gulp and Webpack and Browserify and about a million other things we can use to automatically transpile TypeScript but it's not worth the grief for the purposes of this exercise

Open up your new directory in (preferably VSCode 😜) your favorite text editor and make a new file test.ts. In test.ts we're going to declare a constant called foo:

const foo = 'foo';

Congrats!! you just wrote your first line of TypeScript 🎉
Just kidding kind of... Like I said, TypeScript is just JavaScript.

For our real first line(s) of TypeScript, we're going to gently introduce some cool TS features. Let's start with strong types.

In test.ts write these two lines:

let foo: string = 'foo';
foo = 13;

and run tsc test.ts --w in your terminal (the --w will 'watch' the file and run TypeScript every time it file changes (on save) so we don't need to retype tsc test.ts every time we update the file).

If you're using VSCode, you'll immediately see: Type '13' is not assignable to type 'string' in your editor. If you're using another editor without a TypeScript plugin, you'll see the message in your console. The error message is printed because we're using incompatible types (trying to assign a 'number' to a 'string').

Note: Even with type errors, TypeScript will still spit out a JS file. This is for people migrating existing projects, so they can use TypeScript in their projects, even if some of their types may not be 100% compatible. See this issue for more.

At this point you might be thinking: "ok great this prevents me from assigning a number to a string... whoop-dee-freakin-doo 🙄". This is where we introduce the interface. Interfaces let you define a name for a 'skeleton' of an object and it's properties (and their types), to make sure the value passed to a function or assigned to a variable is the correct type. These really come in handy with PropTypes for my react folk. An interface would be implemented like so:

interface Foo {
  bar: string,
  baz?: number
}

function interfaceTest(foo: Foo) {
  console.log(foo.bar);
  console.log(foo.baz ? foo.baz : `the property "baz" is optional so it does not have to be passed into the function`);
}

interfaceTest({bar: 'bar'});

If you tested this out by yourself, you might be surprised to see that TypeScript didn't yell at us. This is because the property baz is optional (denoted by a question mark after the property name, just before the :). This means that the property doesn't have to be implemented to meet the contract (type requirements) of the interface.

This brings us to type aliases. Type aliases are just like interfaces, but with a few constraints and a cool plus. Type aliases cannot be used for Declaration Merging, a fancy term for a compiler feature that takes multiple interfaces of the same name and turns them into one interface declaration. They also cannot be extended or implemented by classes. The neat thing about type aliases is that we can use them as a variable for literal primitive types (string, number, array... that sort of thing) here is a full list of primitive types. This means that we can store multiple types as one type alias (it'll make much more sense in a demo):

type OptionalStringReturn = string | void;

function foo(str: string): OptionalStringReturn {
    //in here we can elect to return a string, or return nothing
}

This is helpful as functions in TypeScript don't support ? to denote optional values. Interfaces cannot be place holders for primitive types, so type aliases definitely come in handy here. The | says that the value of the property with that type can be any one of the types separated by | in the type alias declaration. You may use as many or as little of these as you'd like.

Thanks so much for making it to the end of my little TypeScript demo. My next TypeScript post will use TS to implement a searchable CollectionView in React.

Thanks Again 🤗
-Harry

Discussion

pic
Editor guide