Skip to content

About

Repo for typescript

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

TypeScript Cheat Sheet

A comprehensive reference for TypeScript - a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.


Table of Contents


Installation and Setup

Installation

# 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

Basic Project Setup

# 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

Basic Types

Primitive Types

// 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 Types

// 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 Types

// 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"
};

Enum Types

// 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;

Interfaces and Type Aliases

Interface Declarations

// 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;
}

Interface Inheritance

// 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

Type Aliases

// 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 and Intersection Types

// 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;
  }
}

Classes and Inheritance

Basic Classes

// 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());

Advanced Class Features

// 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...");
  }
}

Functions

Function Types

// 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 Types and Interfaces

// 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;
}

Generics

Basic Generics

// 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

Advanced Generic Patterns

// 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`;

Utility Types

Built-in Utility Types

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>]

Custom Utility Types

// 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"

Decorators

Class Decorators

// 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 Decorators

// 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 and Parameter Decorators

// 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" };
  }
}

Module System

ES6 Modules

// 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);

CommonJS Modules

// 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 and Module Declaration

// 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;
}

TypeScript Configuration

tsconfig.json

{
  "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"
  ]
}

Project References

{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "rootDir": "./src",
    "outDir": "./lib"
  },
  "references": [
    { "path": "../shared" },
    { "path": "../utils" }
  ]
}

Compiler Options

Strict Type Checking

{
  "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
  }
}

Module Resolution

{
  "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
  }
}

Output Options

{
  "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
  }
}

Advanced Types

Conditional Types

// 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

Mapped Types

// 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];
};

Template Literal Types

// 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"

Best Practices

Type Safety

// 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[];
}

Code Organization

// 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 };
}

Error Handling

// 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";
}

Performance Tips

// 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')>;

Common Patterns

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>

Tooling Integration

Popular TypeScript Tools

# 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

Resources


Author

🤖 casjay: Github 🤖


Originally compiled from various sources. Contributions welcome!

About

Repo for typescript

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors