Elevate your JavaScript with static types and modern tooling
npm install -g typescript
TypeScript is a strongly typed superset of JavaScript that compiles to plain JavaScript. Developed and maintained by Microsoft, it adds optional static typing and class-based object-oriented programming to JavaScript.
| Type | Description | Example |
|---|---|---|
string |
Textual data | let name: string = "Alice"; |
number |
Numeric values (int/float) | let age: number = 30; |
boolean |
True/false values | let isActive: boolean = true; |
any |
Opt-out of type checking | let dynamic: any = "could be anything"; |
unknown |
Type-safe counterpart of any | let notSure: unknown = 4; |
void |
Absence of any type (functions) | function log(): void { console.log('hi'); } |
never |
Values that never occur | function error(message: string): never { throw new Error(message); } |
// Type annotations with different basic typeslet username: string = "typescript_user";let userAge: number = 25;let isAdmin: boolean = true;let userData: any = "Can be anything";let response: unknown = "Needs type checking";// Arrayslet numbers: number[] = [1, 2, 3];let names: Array<string> = ["Alice", "Bob"];// Tuples - fixed length arrayslet user: [string, number, boolean] = ["Alice", 30, true];TypeScript enhances JavaScript functions with parameter types, return types, and function overloading.
// Function with typed parameters and return typefunction add(x: number, y: number): number {return x + y;// Arrow function with typesconst multiply = (a: number, b: number): number => a * b;// Optional parameter (with ?)function greet(name: string, title?: string): string {return title ? `Hello, ${title} ${name}!` : `Hello, ${name}!`;// Default parameterfunction createUser(name: string, role: string = "user"void {console.log(`Created ${name} with role ${role}`);// Function overload signaturesfunction getData(id: number): string;function getData(name: string): string[];// Implementationfunction getData(input: number | string): string | string[] {if (typeof input === "number") {return `Data for ID ${input}`;else {return ["Data 1", "Data 2"];Interfaces define contracts for object shapes and can be extended.
// Basic interfaceinterface User {id: number;name: string;email?: string; // Optional property// Using the interfaceconst currentUser: User = {id: 1,name: "Alice"// Extending interfacesinterface Admin extends User {privileges: string[];Type aliases can represent primitives, unions, tuples, and more.
// Basic type aliastype Point = {x: number;y: number;// Union typestype ID = number | string;// Tuple typetype Data = [string, number];// Function typetype GreetFunction = (name: string) => string;// Intersection typestype AdminUser = User & { isAdmin: true };| Feature | Interface | Type |
|---|---|---|
| Extending | extends keyword |
Intersection (&) |
| Implementing | Can be implemented by class | Cannot be implemented |
| Declaration merging | Multiple declarations merge | Cannot be re-declared |
| Primitives/unions/tuples | No | Yes |
TypeScript adds type annotations and visibility modifiers to ES6 classes.
class Person {// Properties with typesname: string;age: number;// Constructor with parameter propertiesconstructor(name: string, age: number) {this.name = name;this.age = age;// Method with return typedescribe(): string {return `${this.name} is ${this.age} years old.`;// Usageconst person = new Person("Alice", 30);console.log(person.describe());class Employee {// Public by defaultpublic name: string;// Private - only accessible within classprivate salary: number;// Protected - accessible in subclassesprotected department: string;constructor(name: string, salary: number, department: string) {this.name = name;this.salary = salary;this.department = department;// Readonly - can't be modified after initializationreadonly id: number = Math.floor(Math.random() * 1000);interface ClockInterface {currentTime: Date;setTime(d: Date): void;class Clock implements ClockInterface {currentTime: Date = new Date();setTime(d: Date) {this.currentTime = d;constructor(public hour: number, public minute: number) {}class DigitalClock extends Clock {display(): string {return `${this.hour}:${this.minute}`;Generics allow creating reusable components that work with multiple types while maintaining type safety.
// Simple generic functionfunction identity<T>(arg: T): T {return arg;// Usage with explicit typelet output1 = identity<string>("Hello");// Type inferencelet output2 = identity(42);// Generic with multiple typesfunction merge<T, U>(obj1: T, obj2: U): T & U {return { ...obj1, ...obj2 };const merged = merge({ name: "Alice" }, { age: 30 });// Constraint with interfaceinterface Lengthwise {length: number;function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length);return arg;// Now works with arrays and stringsloggingIdentity([1, 2, 3]);loggingIdentity("hello");// Keyof constraintfunction getProperty<T, K extends keyof T>(obj: T, key: K) {return obj[key];class GenericNumber<T> {zeroValue: T;add: (x: T, y: T) => T;constructor(zeroValue: T, add: (x: T, y: T) => T) {this.zeroValue = zeroValue;this.add = add;// Usage with numberlet myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);// Usage with stringlet stringNumeric = new GenericNumber<string>("", (x, y) => x + y);// Union type - value can be one of several typesfunction printId(id: number | string) {console.log(`ID: ${id}`);// Type guards with typeoffunction printIdSafe(id: number | string) {if (typeof id === "string") {console.log(id.toUpperCase());else {console.log(id.toFixed(2));// Intersection type - combines multiple typestype Admin = {name: string;privileges: string[];type Employee = {name: string;startDate: Date;type ElevatedEmployee = Admin & Employee;// Type guard with 'in' operatorinterface Bird {fly(): void;layEggs(): void;interface Fish {swim(): void;layEggs(): void;function getSmallPet(): Fish | Bird {return Math.random() > 0.5 ? { fly: () => {}, layEggs: () => {} } : { swim: () => {}, layEggs: () => {} };function move(pet: Fish | Bird) {if ("swim" in pet) {return pet.swim();return pet.fly();// Discriminated union with 'kind' propertyinterface Square {kind: "square";size: number;interface Circle {kind: "circle";radius: number;type Shape = Square | Circle;function area(shape: Shape): number {switch (shape.kind) {case "square": return shape.size * shape.size;case "circle": return Math.PI * shape.radius ** 2;TypeScript provides several utility types to facilitate common type transformations.
| Utility Type | Description | Example |
|---|---|---|
Partial<T> |
Makes all properties in T optional | Partial<User> |
Required<T> |
Makes all properties in T required | Required<User> |
Readonly<T> |
Makes all properties in T readonly | Readonly<User> |
Record<K,T> |
Constructs an object type with property keys of type K and values of type T | Record<string, number> |
Pick<T,K> |
Picks a set of properties K from T | Pick<User, "name" | "email"> |
Omit<T,K> |
Omits a set of properties K from T | Omit<User, "password"> |
Exclude<T,U> |
Excludes from T those types that are assignable to U | Exclude<string | number, number> |
Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members.
// Simple decorator that logs class constructionfunction logged(constructor: Function) {console.log(`Class ${constructor.name} was defined`);// Applying the decorator@loggedclass Greeter {greeting: string;constructor(message: string) {this.greeting = message;greet() {return `Hello, ${this.greeting}`;// Decorator factory that logs method callsfunction logMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;// Replace the original method with a wrapperdescriptor.value = function (...args: any[]) {console.log(`Calling ${propertyKey} with args: ${JSON.stringify(args)}`);const result = originalMethod.apply(this, args);console.log(`Method ${propertyKey} returned: ${JSON.stringify(result)}`);return result;return descriptor;class Calculator {@logMethodadd(x: number, y: number): number {return x + y;// Property decorator that adds metadatafunction format(formatString: string) {return function (target: any, propertyKey: string) {console.log(`Property ${propertyKey} will be formatted with: ${formatString}`);// Parameter decoratorfunction validate(target: any, propertyKey: string, parameterIndex: number) {console.log(`Validating parameter ${parameterIndex} of ${propertyKey}`);class Greeter {@format("Hello, %s")greeting: string;constructor(message: string) {this.greeting = message;greet(@validate name: string) {return `${this.greeting}, ${name}`;The tsconfig.json file specifies the root files and the compiler options required to compile the project.
// Example tsconfig.json{"compilerOptions": {"target": "ES6","module": "commonjs","strict": true,"esModuleInterop": true,"skipLibCheck": true,"forceConsistentCasingInFileNames": true,"outDir": "./dist","rootDir": "./src","baseUrl": ".","paths": {"@/*": ["src/*"]"include": ["src/**/*"],"exclude": ["node_modules"]}