Typescript Basics for Javascript Developers

“The main benefit of TypeScript is that it can highlight unexpected behavior in your code, lowering the chance of bugs.” – Typescript Documentation

Typescript tells your code editor what your code is supposed to look like so that it can warn you of errors as you type. The benefit of this is mostly code hinting and finding errors before you compile. It doesn’t sound like much of a benefit, but it is significant for larger applications.

Typescript used to be optional for Javascript developers, but it has quickly become a required skill. You’ll see it a lot in React, Angular, and other frameworks, so let’s go over the basics.

Here’s a simple example of Typescript.

// without typescript
let country = "Zimbabwe";
// with typescript
let country:string = "Zimbabwe";

If I then use the variable “country” the wrong way, Typescript will tell me about it immediately. (I am using VS Code)

This is a simple example, but as your code gets more complex, Typescript can help you find and fix errors before they become bugs.

Typescript is a superset of Javascript, meaning is an addition to Javascript. You can write any Javascript you want in a .ts file, along with typescript.

Usage

To use Typescript, you must create a new project and install typescript:

npm install typescript

Next, create a new file called example.ts. Notice the .ts extension, that will tell our code editor to treat this as a typescript file. Now we will start seeing red squiggly lines in our code when Typescript finds a problem.

In the above example we defined a variable as a number, then assigned it a string value. We can hover over the red underlined variable and we will get a hint that tells us what is wrong. You can also press command or control while hovering over it to see more information.

Type Definitions

When declaring a type, you can instantiate them with a value or null.

Booleans, Numbers, and Strings

let isLoading:boolean;
// or
let isLoading:boolean = false;
let index:number = 0;
let user:undefined;
let username:string = "Scott";

Arrays

let salaries:number[] = [ 50000,55000,60000 ];
// this is exactly the same
let salaries:Array<number> = [ 50000,55000,60000 ];
const posts:Object[] = [{ id:1, title:"One", id: 2, title: "Two" } ];
// you can use any if you don't know what your data will look like
let mixedArray:any[];

More complex arrays are covered in the interfaces section below.

Functions

// simple function
const getProducts:Function = () => {}

Defining a simple function is not useful, Typescript will infer that on its own. By defining a type for a function, you can tell Typescript what the argument and return value should be.

// id is either a number or string, and we return a number
type GetIdFunction = ( id: number | string ) => number;
function getTheId( id ):GetIdFunction {
    return parseInt( id );
}

Objects

const user:Object = {"username":"Scott", id: 1};

It’s not super helpful to simply define an array, object, or function without any other information. What if you are manipulating a user object for your application and you forget if you should used id, ID, or databaseId as they key? That’s where defining an interface will help.

Interfaces

An interface allows you to create a specific type for an object. For example:

interface Product {
  name: string;
  id: number;
  price: number;
}

Now we can use this Product interface.

// this function returns a product
function getProduct(id:number):Product  {
    // ...
}
// this function accepts a product as an argument
function deleteProduct( product:Product)  {
    // ...
}

Now when we access the product, we will get some useful code hinting.

Typescript also alerts us if we are using our interface improperly.

Generics

What if you want to use the same type multiple times? Generics let you label a type with a name (like Posts or Products) so it’s easy to reuse later.

type Numbers = Array<number>;
let numbers:Numbers = [1,2,3];
type Countries = Array<string>;
let countries:Countries = ["US","MX","CA"];
type Posts = Array<Object>;
let posts:Posts = [{id: 1, title: "One"}, {id: 2, title: "Two"}]

We can also get more specific by swapping out “Object” for the specific object values we are using.

type Posts = Array<{ id:number; title:string; }>;

We can get even more concise by using an interface along with a generic. You’ll see this pattern a lot.

interface Posts {
 id: number;
 title: string;
}
type Posts = Array<Posts>;
const posts:Posts = [
    {
        id: 1,
        title: "One"
    },
    {
        id: 2,
        title: "Two"
    }
]

Extending Existing Types

What if you need to add a field to an existing type? Of course you can simply add it to your type or interface, but what if it’s from a library and you don’t have access to the original type definition?

This recently happened to me. To fix it, you can extend the type. In my case, the MediaFile type was missing a property called localURL. So when I tried to use MediaFile.localURL I got the dreaded red squiggly line. To fix it, I extended the MediaFile type like this:

interface ExtendedMedia extends MediaFile {
  localURL: string
}

Building on the Basics

This post covered the basics of Typescript, next you’ll want to learn how it’s used in an application. For example, how to import pre-existing types, how to export reusable interfaces, and the specifics of Typescript in a framework like React.


Posted

in

by