Woman on Computer

Web development is moving at an incredible velocity nowadays. Both aspiring and experienced front-end developers found this post entertaining. When I heard about TypeScript, I thought, "Great, another front-end framework I need to learn," especially considering Angular 2 was written in TypeScript.

But no.

TypeScript is easy to learn. It is a superset of JavaScript that vastly improves testing and maintainability. It helps write solid, enterprise-scale JavaScript applications. It is a compiler - erm, transpiler - that converts .ts files to perfectly compatible .js files. TypeScript is also pretty fun to write, too, thanks to its beautiful syntactic sugar and the smart type checking that's baked in. In supporting environments, we can see errors in-line as we make changes to a TypeScript document. Let's take a look some of this type checking in action. Each example targets TypeScript 2.1.4.

Beginner-level Type Checking

TypeScript empowers developers to assign types to variables. In addition to string, number, and boolean, TypeScript also supports array, tuple, null, undefined, and others. User-defined classes and functions can also be used. An important point to note is that, without compiler options set, null and undefined can be assigned to any type. The any type, meanwhile, was created to optionally skip compile-time type checks - it can have any type assigned to it.

let a: string;
let b: number;
let c: any;
let someObj: { firstName: string, lastName: string, callback: () => void };
let someFunc: (obj: { id: number, name: string, phone: number }) => void; // Function typing, with a return type!

a = "Hey, I'm a string!";
a = null; // Ok, since undefined is a subtype of string.
a = undefined; // Ok, since undefined is a subtype of string.

b = 10;
b = "Hey, I'm trying to be a string!"; // Compiler Error: Type 'string' is not assignable to type 'number'.

c = [10, "Hey, I'm a tuple!"];
console.log(`${c[0]} ${c[1]}`); // 10 Hey, I'm a tuple! // Compiler Error: Property 'phone' does not exist on type '{ firstName: string, lastName: string }'.
someObj.callback = function () { someFunc({ id: 1, name: `First Last`, phone: 1234567890 }) };

Our text editor compiled the above code and detected some errors - Pretty cool! Assigning explicit types to variables is a great idea to avoid logic errors.

--strictNullChecks Compile-time Option

When the --strictNullChecks compiler option is enabled, null and undefined are treated as separate types. Both are no longer subtypes of other types, and the compiler will enforce that. The only exception, according to the documentation, is that undefined can still be assigned to variables of type void. --strictNullChecks will also not allow variable references to be made without an assignment.

// --strictNullChecks turned ON.
let a: any;
let b: number;
let c: string = "Hey, I'm a string!"; // Declaration with assignment.
let d: void;

a; // Ok, because foo is of type any.
b; // Compiler Error: Variable 'bar' is used before it is assigned.
c = null; // Compiler Error: Type 'null' is not assignable to type string.
d = undefined; // Ok, void type is assigned undefined.

Union Types

If a variable can be typeA or typeB, enter the union type. A union type is created by delimiting each type with a vertical pipe.

// --strictNullChecks turned ON.
class ClassA { }
class ClassB { }

let a: ClassA | ClassB | null;
let b: Array;
let c: number | string;

a = null; // Ok, because 'null' is included in the union type.
b = null; // Compiler Error: Type 'null' is not assignable to type 'ClassA[]'.
c = 4;
c = "I'm a string now!"; // Ok, because 'string' is included in the union type.

Type Assertions

Compile-time type assertions are available in TypeScript, and there are two ways. Both methods below in the example are functionally the same; the as method is the recommended syntax, per the documentation. Remember: This is at compile-time! Run-time checking would be highly recommended in this scenario.

class SomeClass {
 name: string;
 // ...

function someFunc(val: any) {
 let a = val;
 let b = val as SomeClass; // Recommended

 // OR: Without declaring...

 ( val).name = "First Last";
 (val as SomeClass).name = "First Last";

String Literal Types

When a string property is expected to be set to a finite set values, the string literal type is the way to go. Assignments to variables of a string literal type must match the available options, or the compiler errors out.

type Region = "Mid Atlantic" | "Northeast" | "Midwest";

class SomeClass {
 someFunc(region: Region) {
 // ...

const someObj = new SomeClass();
someObj.someFunc("Mid Atlantic"); // Ok, because the string is a valid literal for type Region.
someObj.someFunc("Southwest"); // Compiler Error: Argument of type 'Southwest' is not assignable to parameter of type 'Region'.

More intuitive type inferencing in 2.1

TypeScript 2.1, released last December, delivers more intuitive type inference for variables and arrays absent of a declaration type.

When a variable or array is declared without a type, TypeScript infers it to be any - an implicit any, that is. The --noImplicitAny option gives us smarter type inference and flexibility when we need to work with variables whose types are expected to change.

// --noImplicitAny turned ON.
let a;
a = 3; // Compiler knows type of a is 'number'.

a.substring(5); // Compiler Error: Property 'substring' does not exist on type 'number'.

a = "Hey, I'm a string!"; // Type of a is now 'string'.

console.log(a.substring(5)); // I'm a string!


TypeScript makes JavaScript development safer, more maintainable, and easier to write enterprise-scale applications. To get started, visit the TypeScript website, and check out the Playground to start writing code now.

Neward, Ted. "Busy Developer's Guide to TypeScript." Visual Studio, Live!, 5 October, 2016, Renaissance Hotel, Washington, D.C.