Skip to content

TypeScript Types

If JavaScript is the wild west where anything goes, TypeScript is the sheriff that brings law and order to town. Dealing with types might feel like extra paperwork at first, but it saves you from shooting yourself in the foot later on.

In this guide, we’ll explore the bread and butter of TypeScript: its type system. We’ll start with the primitives you know and love, and work our way up to the complex structures that make TypeScript a superpower for large-scale applications.

These are the building blocks. If you’ve written JavaScript, you know these. TypeScript just asks you to be explicit about them (sometimes).

The trifecta of primitives.

// boolean - simple true/false flags
let isCool: boolean = false;
// number - for all your floating point needs
let age: number = 56;
// string - text
let favoriteQuote: string = `I'm not old, I'm dirt`;

These two are often the source of many runtime errors. TypeScript helps you handle them safely.

let meh: undefined = undefined;
let noo: null = null;

Now we’re getting into the interesting stuff. How do we describe objects and collections?

There are two ways to define arrays. Both are valid, pick your style.

// Syntax 1: Type[]
let pets: string[] = ['cat', 'mouse', 'dragon'];
// Syntax 2: Array<Type> (Generics syntax)
let pets2: Array<string> = ['pig', 'lion', 'cheetah'];

Arrays with a fixed number of elements and known types. Great for simple coordinate pairs or key-value structures.

// Represents a [name, quantity] pair
let basket: [string, number];
basket = ['basketball', 10]; // OK
// basket = [10, 'basketball']; // Error: Type 'number' is not assignable to type 'string'.

A way to give friendly names to sets of numeric values.

enum Size {
Small = 1,
Medium = 2,
Large = 3,
}
let sizeName: string = Size[2];
console.log(sizeName); // Displays 'Medium'

The “Escape Hatch”. any disables type checking. Use it sparingly, or better yet, don’t use it at all if you can avoid it.

let whatever: any = 'aaaaghhhhhh noooooo!';
whatever = 42; // legitimate in some rare cases, but dangerous

Used for functions that do not return a value.

const sing = (): void => console.log('Lalalala');

Represents the type of values that never occur. Commonly used for functions that always throw an exception or never return.

let error = (): never => {
throw Error('blah!');
};

This is a common point of confusion. Both can describe the shape of an object, but they have subtle differences.

Interfaces are primarily used to define the structure of objects. They can be extended (merged).

interface RobotArmy {
count: number;
type: string;
magic?: string; // Optional property
}
// Function using the interface
const fightRobotArmy = (robots: RobotArmy): void => {
console.log(`FIGHT! ${robots.count} ${robots.type} robots attacking.`);
};

Types are more flexible. They can define unions, primitives, tuples, and more.

// Union Type
type AnimalType = 'cat' | 'mouse' | 'dragon';
// Object Type
type CatArmy = {
count: number;
type: string;
}
// Type Assertion (Casting)
const dog = {} as CatArmy;
dog.count = 5;

TypeScript adds full object-oriented support with access modifiers like public, private, and protected.

class Animal {
// parameter properties shorthand
constructor(private sound: string) {}
greet(): string {
return `Hello, ${this.sound}`;
}
}
const lion = new Animal('Roar');
// lion.sound; // Error: Property 'sound' is private and only accessible within class 'Animal'.
console.log(lion.greet()); // 'Hello, Roar'

TypeScript’s type system is deep, but these fundamentals cover 90% of what you’ll use daily. By defining your data structures explicitly, you turn runtime errors into compile-time errors, and that is a massive win for productivity.