A comprehensive reference for TypeScript - a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
- Installation and Setup
- Basic Types
- Interfaces and Type Aliases
- Classes and Inheritance
- Functions
- Generics
- Utility Types
- Decorators
- Module System
- TypeScript Configuration
- Compiler Options
- Advanced Types
- Best Practices
# Install TypeScript globally
npm install -g typescript
# Install for a project
npm install --save-dev typescript
# Check version
tsc --version
# Initialize TypeScript project
tsc --init
# Compile TypeScript file
tsc app.ts
# Watch mode
tsc --watch# Create new project
mkdir my-ts-project
cd my-ts-project
npm init -y
npm install --save-dev typescript @types/node
# Create tsconfig.json
npx tsc --init
# Create basic TypeScript file
echo 'console.log("Hello, TypeScript!");' > index.ts
# Compile and run
npx tsc
node index.js// Boolean
let isDone: boolean = false;
// Number
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
// String
let color: string = "blue";
let fullName: string = `Bob Bobbington`;
let age: number = 37;
let sentence: string = `Hello, my name is ${fullName}.`;
// Null and Undefined
let u: undefined = undefined;
let n: null = null;
// Void (typically for function return types)
function warnUser(): void {
console.log("This is my warning message");
}
// Never (functions that never return)
function error(message: string): never {
throw new Error(message);
}
// Any (avoid when possible)
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;
// Unknown (safer than any)
let userInput: unknown;
let userName: string;
if (typeof userInput === "string") {
userName = userInput; // Type guard required
}// Array syntax
let list: number[] = [1, 2, 3];
let names: string[] = ["Alice", "Bob", "Charlie"];
// Generic array type
let values: Array<number> = [1, 2, 3];
// Readonly arrays
let readonlyArray: ReadonlyArray<number> = [1, 2, 3];
// readonlyArray.push(4); // Error!
// Tuple types
let x: [string, number];
x = ["hello", 10]; // OK
// x = [10, "hello"]; // Error!
// Optional tuple elements
let optionalTuple: [string, number?] = ["hello"];
// Rest elements in tuples
let restTuple: [string, ...number[]] = ["hello", 1, 2, 3];// Object type annotation
let person: { name: string; age: number } = {
name: "Alice",
age: 30
};
// Optional properties
let config: { host: string; port?: number } = {
host: "localhost"
};
// Readonly properties
let point: { readonly x: number; readonly y: number } = {
x: 10,
y: 20
};
// point.x = 5; // Error!
// Index signatures
let dictionary: { [key: string]: string } = {
name: "Alice",
city: "New York"
};// Numeric enum
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// String enum
enum Color {
Red = "red",
Green = "green",
Blue = "blue"
}
// Heterogeneous enum (mixed)
enum BooleanLikeEnum {
No = 0,
Yes = "YES"
}
// Const enum (inlined at compile time)
const enum Directions {
Up,
Down,
Left,
Right
}
// Usage
let direction: Direction = Direction.Up;
let color: Color = Color.Red;// Basic interface
interface User {
id: number;
name: string;
email: string;
age?: number; // Optional property
}
// Interface with methods
interface Calculator {
add(a: number, b: number): number;
subtract(a: number, b: number): number;
}
// Interface with index signature
interface StringArray {
[index: number]: string;
}
// Interface with call signature
interface GreetFunction {
(name: string): string;
}
// Interface with construct signature
interface ClockConstructor {
new (hour: number, minute: number): Clock;
}
interface Clock {
currentTime: Date;
setTime(d: Date): void;
}// Extending interfaces
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
bark(): void;
}
// Multiple inheritance
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
interface Duck extends Animal, Flyable, Swimmable {
quack(): void;
}
// Interface merging
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
// Now Window has both title and ts properties// Basic type alias
type ID = string | number;
type Status = "pending" | "approved" | "rejected";
// Object type alias
type Point = {
x: number;
y: number;
};
// Function type alias
type Operation = (a: number, b: number) => number;
// Generic type alias
type Container<T> = {
value: T;
};
// Conditional type alias
type NonNullable<T> = T extends null | undefined ? never : T;
// Mapped type alias
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};// Union types
type StringOrNumber = string | number;
type Theme = "light" | "dark";
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
// Intersection types
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
let circle: ColorfulCircle = {
color: "red",
radius: 10
};
// Discriminated unions
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
type Shape = Square | Rectangle;
function area(shape: Shape): number {
switch (shape.kind) {
case "square":
return shape.size * shape.size;
case "rectangle":
return shape.width * shape.height;
}
}// Basic class
class Animal {
private name: string;
protected species: string;
public age: number;
constructor(name: string, species: string, age: number) {
this.name = name;
this.species = species;
this.age = age;
}
public getName(): string {
return this.name;
}
protected makeSound(): void {
console.log("Some generic animal sound");
}
}
// Inheritance
class Dog extends Animal {
private breed: string;
constructor(name: string, age: number, breed: string) {
super(name, "Canine", age);
this.breed = breed;
}
public bark(): void {
this.makeSound(); // Can access protected method
console.log("Woof! Woof!");
}
public getBreed(): string {
return this.breed;
}
}
// Usage
const myDog = new Dog("Buddy", 3, "Golden Retriever");
myDog.bark();
console.log(myDog.getBreed());// Abstract classes
abstract class Shape {
abstract area(): number;
displayArea(): void {
console.log(`Area: ${this.area()}`);
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
}
// Static members
class MathUtils {
static PI: number = 3.14;
static calculateCircumference(radius: number): number {
return 2 * MathUtils.PI * radius;
}
}
// Getter and setter
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
if (value.length > 0) {
this._name = value;
}
}
}
// Parameter properties
class Point {
constructor(
public x: number,
public y: number,
private z: number = 0
) {}
}
// Interface implementation
interface Flyable {
fly(): void;
}
class Bird implements Flyable {
fly(): void {
console.log("Flying...");
}
}// Function declarations
function add(x: number, y: number): number {
return x + y;
}
// Function expressions
const multiply = function(x: number, y: number): number {
return x * y;
};
// Arrow functions
const divide = (x: number, y: number): number => x / y;
// Optional parameters
function buildName(firstName: string, lastName?: string): string {
if (lastName) {
return firstName + " " + lastName;
}
return firstName;
}
// Default parameters
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
// Rest parameters
function buildNameList(firstName: string, ...restOfName: string[]): string {
return firstName + " " + restOfName.join(" ");
}
// Function overloads
function createDate(timestamp: number): Date;
function createDate(year: number, month: number, day: number): Date;
function createDate(timestampOrYear: number, month?: number, day?: number): Date {
if (month !== undefined && day !== undefined) {
return new Date(timestampOrYear, month - 1, day);
}
return new Date(timestampOrYear);
}// Function type expressions
type GreetFunction = (name: string) => string;
// Call signatures
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};
// Construct signatures
type SomeConstructor = {
new (s: string): Date;
};
// Generic functions
function identity<T>(arg: T): T {
return arg;
}
function map<T, U>(array: T[], func: (item: T) => U): U[] {
return array.map(func);
}
// Generic constraints
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// Type guards
function isString(value: any): value is string {
return typeof value === "string";
}
function padLeft(value: string, padding: string | number) {
if (isString(padding)) {
return padding + value;
}
return Array(padding + 1).join(" ") + value;
}// Generic functions
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString");
let output2 = identity("myString"); // Type inference
// Generic interfaces
interface GenericIdentityFn<T> {
(arg: T): T;
}
// Generic classes
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
// Generic constraints
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// Using type parameters in generic constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // OK
// getProperty(x, "m"); // Error// Generic factory functions
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = "Mikle";
}
class Animal {
numLegs: number = 4;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask;
// Conditional types
type ApiResponse<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: object;
// Mapped types
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
// Template literal types
type EmailLocaleIDs = "welcome_email" | "email_heading";
type FooterLocaleIDs = "footer_title" | "footer_sendoff";
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;interface User {
id: number;
name: string;
email: string;
age?: number;
}
// Partial<T> - Makes all properties optional
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number; }
// Required<T> - Makes all properties required
type RequiredUser = Required<User>;
// { id: number; name: string; email: string; age: number; }
// Readonly<T> - Makes all properties readonly
type ReadonlyUser = Readonly<User>;
// Pick<T, K> - Pick specific properties
type UserContactInfo = Pick<User, "name" | "email">;
// { name: string; email: string; }
// Omit<T, K> - Omit specific properties
type UserWithoutId = Omit<User, "id">;
// { name: string; email: string; age?: number; }
// Record<K, T> - Create object type with specific keys and values
type UserRoles = Record<"admin" | "user" | "guest", boolean>;
// { admin: boolean; user: boolean; guest: boolean; }
// Exclude<T, U> - Exclude types from union
type AllowedColors = "red" | "green" | "blue" | "yellow";
type PrimaryColors = Exclude<AllowedColors, "yellow">;
// "red" | "green" | "blue"
// Extract<T, U> - Extract types from union
type StringOrNumber = string | number | boolean;
type StringAndNumber = Extract<StringOrNumber, string | number>;
// string | number
// NonNullable<T> - Remove null and undefined
type NonNullableString = NonNullable<string | null | undefined>;
// string
// ReturnType<T> - Get function return type
function getUser(): User {
return { id: 1, name: "Alice", email: "alice@example.com" };
}
type UserReturnType = ReturnType<typeof getUser>; // User
// Parameters<T> - Get function parameter types
function updateUser(id: number, updates: Partial<User>): void {}
type UpdateUserParams = Parameters<typeof updateUser>;
// [number, Partial<User>]// Deep partial
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// Mutable (opposite of Readonly)
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
// Optional by keys
type OptionalByKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// Required by keys
type RequiredByKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
// Function property names
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
// Non-function property names
type NonFunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
// Example usage
interface Example {
name: string;
age: number;
greet(): void;
calculate(x: number): number;
}
type ExampleFunctions = FunctionPropertyNames<Example>; // "greet" | "calculate"
type ExampleProperties = NonFunctionPropertyNames<Example>; // "name" | "age"// Enable decorators in tsconfig.json:
// "experimentalDecorators": true
// Basic decorator
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
// Decorator factory
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
@classDecorator
class Greeter2 {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}// Method decorator
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
// Log decorator
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyName} with arguments:`, args);
const result = method.apply(this, args);
console.log(`${propertyName} returned:`, result);
return result;
};
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}// Property decorator
function format(formatString: string) {
return function (target: any, propertyKey: string) {
let value = target[propertyKey];
const getter = () => value;
const setter = (newVal: string) => {
value = `${formatString} ${newVal}`;
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
};
}
class Greeter {
@format("Hello")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
}
// Parameter decorator
function validate(target: any, propertyKey: string, parameterIndex: number) {
console.log(`Validating parameter ${parameterIndex} of ${propertyKey}`);
}
class UserService {
getUser(@validate id: number) {
return { id, name: "User" };
}
}// math.ts - Named exports
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
export const PI = 3.14159;
// Default export
export default function multiply(a: number, b: number): number {
return a * b;
}
// Re-exports
export { divide } from './division';
export * from './constants';
// app.ts - Imports
import multiply, { add, subtract, PI } from './math';
import { divide } from './math';
import * as MathUtils from './math';
// Usage
console.log(add(5, 3));
console.log(multiply(4, 2));
console.log(MathUtils.PI);// math.ts
function add(a: number, b: number): number {
return a + b;
}
function subtract(a: number, b: number): number {
return a - b;
}
module.exports = { add, subtract };
// app.ts
const { add, subtract } = require('./math');
import math = require('./math'); // TypeScript syntax// Namespace declaration
namespace Geometry {
export interface Point {
x: number;
y: number;
}
export function distance(p1: Point, p2: Point): number {
return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
}
}
// Usage
let point1: Geometry.Point = { x: 0, y: 0 };
let point2: Geometry.Point = { x: 3, y: 4 };
console.log(Geometry.distance(point1, point2));
// Module declaration for external libraries
declare module "lodash" {
export function chunk<T>(array: T[], size: number): T[][];
export function isEqual(value: any, other: any): boolean;
}
// Ambient module declaration
declare module "*.json" {
const value: any;
export default value;
}{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
},
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts"
]
}{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"rootDir": "./src",
"outDir": "./lib"
},
"references": [
{ "path": "../shared" },
{ "path": "../utils" }
]
}{
"compilerOptions": {
"strict": true, // Enable all strict checks
"noImplicitAny": true, // Error on expressions with 'any' type
"strictNullChecks": true, // Enable strict null checks
"strictFunctionTypes": true, // Enable strict checking of function types
"strictBindCallApply": true, // Enable strict 'bind', 'call', and 'apply'
"strictPropertyInitialization": true, // Ensure properties are initialized
"noImplicitReturns": true, // Error when not all paths return a value
"noFallthroughCasesInSwitch": true, // Error on fallthrough cases
"noUncheckedIndexedAccess": true, // Add undefined to index signature results
"noImplicitOverride": true, // Ensure override members are marked
"exactOptionalPropertyTypes": true // Interpret optional properties exactly
}
}{
"compilerOptions": {
"moduleResolution": "node", // Module resolution strategy
"baseUrl": "./", // Base directory for relative modules
"paths": { // Path mapping for module names
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
},
"typeRoots": [ // Directories for type definitions
"./node_modules/@types",
"./src/types"
],
"types": ["node", "jest"], // Type packages to include
"allowSyntheticDefaultImports": true, // Allow default imports from modules
"esModuleInterop": true, // Enable ES module interoperability
"resolveJsonModule": true // Allow importing JSON modules
}
}{
"compilerOptions": {
"target": "ES2020", // JavaScript version to compile to
"module": "commonjs", // Module system to use
"lib": ["ES2020", "DOM"], // Library files to include
"outDir": "./dist", // Output directory
"outFile": "./bundle.js", // Single output file
"rootDir": "./src", // Root of input files
"removeComments": true, // Remove comments from output
"noEmit": true, // Don't emit outputs
"noEmitOnError": true, // Don't emit if there are errors
"preserveConstEnums": true, // Don't erase const enum declarations
"declaration": true, // Generate .d.ts files
"declarationMap": true, // Generate sourcemaps for .d.ts files
"sourceMap": true, // Generate sourcemaps
"inlineSourceMap": true, // Emit single file with sourcemaps
"inlineSources": true // Emit source alongside sourcemaps
}
}// Basic conditional type
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object";
type T1 = TypeName<string>; // "string"
type T2 = TypeName<"a">; // "string"
type T3 = TypeName<true>; // "boolean"
// Distributive conditional types
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>; // string[] | number[]
// Infer keyword
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type Flatten<T> = T extends (infer U)[] ? U : T;
// Conditional type constraints
type MessageOf<T> = T extends { message: infer M } ? M : never;
interface Email {
message: string;
}
interface Dog {
bark(): void;
}
type EmailMessageContents = MessageOf<Email>; // string
type DogMessageContents = MessageOf<Dog>; // never// Basic mapped type
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// Optional mapped type
type Partial<T> = {
[P in keyof T]?: T[P];
};
// Key remapping
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
type LazyPerson = Getters<Person>;
// {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }
// Filtering with template literal types
type RemoveKindField<Type> = {
[Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};
// Conditional property types
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};// Basic template literal types
type World = "world";
type Greeting = `hello ${World}`; // "hello world"
// Template literal with unions
type EmailLocaleIDs = "welcome_email" | "email_heading";
type FooterLocaleIDs = "footer_title" | "footer_sendoff";
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
// Pattern matching with template literals
type ExtractRouteParams<T> = T extends `${string}:${infer Param}/${infer Rest}`
? { [K in Param | keyof ExtractRouteParams<`/${Rest}`>]: string }
: T extends `${string}:${infer Param}`
? { [K in Param]: string }
: {};
type RouteParams = ExtractRouteParams<"/users/:id/posts/:postId">;
// { id: string; postId: string; }
// String manipulation types
type Uppercase<S extends string> = intrinsic;
type Lowercase<S extends string> = intrinsic;
type Capitalize<S extends string> = intrinsic;
type Uncapitalize<S extends string> = intrinsic;
type LoudGreeting = Uppercase<"Hello">; // "HELLO"
type QuietGreeting = Lowercase<"HELLO">; // "hello"
type CapitalizedName = Capitalize<"alice">; // "Alice"// Use strict configuration
// "strict": true in tsconfig.json
// Prefer type annotations for function parameters and return types
function processUser(user: User): UserResult {
// Implementation
}
// Use type assertions sparingly and prefer type guards
function isString(value: unknown): value is string {
return typeof value === "string";
}
// Avoid 'any' type - use 'unknown' instead
function processValue(value: unknown): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return String(value);
}
// Use const assertions for immutable data
const colors = ["red", "green", "blue"] as const;
type Color = typeof colors[number]; // "red" | "green" | "blue"
// Prefer readonly for immutable data structures
interface ReadonlyConfig {
readonly apiUrl: string;
readonly timeout: number;
readonly features: readonly string[];
}// Group related types in modules
export namespace API {
export interface User {
id: string;
name: string;
email: string;
}
export interface CreateUserRequest {
name: string;
email: string;
}
export interface UpdateUserRequest extends Partial<CreateUserRequest> {
id: string;
}
}
// Use barrel exports for cleaner imports
// index.ts
export * from './types';
export * from './utils';
export * from './services';
// Prefer composition over inheritance
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
class Duck implements Flyable, Swimmable {
fly() { console.log("Flying"); }
swim() { console.log("Swimming"); }
}
// Use factory functions for complex object creation
interface DatabaseConfig {
host: string;
port: number;
database: string;
}
function createDatabaseConfig(
host: string,
port: number = 5432,
database: string = "default"
): DatabaseConfig {
return { host, port, database };
}// Use discriminated unions for error handling
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
function divide(a: number, b: number): Result<number> {
if (b === 0) {
return { success: false, error: new Error("Division by zero") };
}
return { success: true, data: a / b };
}
// Custom error types
class ValidationError extends Error {
constructor(
message: string,
public field: string,
public code: string
) {
super(message);
this.name = "ValidationError";
}
}
// Type-safe error handling
function handleApiError(error: unknown): string {
if (error instanceof ValidationError) {
return `Validation failed for ${error.field}: ${error.message}`;
}
if (error instanceof Error) {
return error.message;
}
return "An unknown error occurred";
}// Use type-only imports/exports
import type { User } from './types';
export type { DatabaseConfig } from './config';
// Prefer interfaces over type aliases for object types
interface User { // Better for performance
id: string;
name: string;
}
type User = { // Acceptable but less optimal
id: string;
name: string;
};
// Use const assertions to avoid unnecessary type widening
const config = {
apiUrl: "https://api.example.com",
version: "v1"
} as const;
// Lazy load types for large codebases
type LazyModule = () => Promise<typeof import('./large-module')>;| Pattern | Use Case | Example |
|---|---|---|
| Builder | Complex object construction | UserBuilder.create().setName().setEmail().build() |
| Factory | Object creation abstraction | createUser(type: 'admin' | 'user') |
| Observer | Event handling | EventEmitter<Events> |
| Strategy | Algorithm selection | PaymentProcessor<PayPal | Stripe> |
# ESLint with TypeScript
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
# Prettier for formatting
npm install --save-dev prettier
# Jest for testing
npm install --save-dev jest @types/jest ts-jest
# Webpack with TypeScript
npm install --save-dev ts-loader webpack
# Vite for modern bundling
npm install --save-dev vite @vitejs/plugin-react- Official TypeScript Documentation
- TypeScript Handbook
- TypeScript Playground
- DefinitelyTyped
- TypeScript ESLint
🤖 casjay: Github 🤖
Originally compiled from various sources. Contributions welcome!