NarvikHub Logo

NARVIKHUB

Tools

Typescript Advanced Patterns

Programming

2024-08-31

TypeScript Advanced Patterns: Type-Safe Development at Scale

Master advanced TypeScript patterns including generics, conditional types, mapped types, and type guards.

TypeScriptJavaScriptType SafetyProgramming

TypeScript's powerful type system enables building robust, maintainable applications at scale. This guide explores advanced patterns including generics, conditional types, utility types, and type-safe design patterns.

Generics and Constraints

// Generic function with constraints

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {

return obj[key];

}

// Generic interface with default type

interface ApiResponse<T = unknown> {

data: T;

status: number;

message: string;

}

// Generic class with multiple type parameters

class DataStore<K extends string | number, V> {

private store = new Map<K, V>();

set(key: K, value: V): void {

this.store.set(key, value);

}

get(key: K): V | undefined {

return this.store.get(key);

}

}

// Conditional generic constraints

type IsArray<T> = T extends any[] ? true : false;

type ArrayElement<T> = T extends (infer U)[] ? U : never;

Conditional and Mapped Types

Conditional Types

// Conditional type for extracting promise value

type Awaited<T> = T extends Promise<infer U> ? U : T;

// Distributive conditional types

type NonNullable<T> = T extends null | undefined ? never : T;

// Function return type extraction

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

// Complex conditional logic

type TypeName<T> =

T extends string ? "string" :

T extends number ? "number" :

T extends boolean ? "boolean" :

T extends undefined ? "undefined" :

T extends Function ? "function" :

"object";

Mapped Types

// Make all properties optional

type Partial<T> = {

[P in keyof T]?: T[P];

};

// Make all properties readonly

type Readonly<T> = {

readonly [P in keyof T]: T[P];

};

// Create type with specific keys

type Pick<T, K extends keyof T> = {

[P in K]: T[P];

};

// Custom mapped type with template literals

type Getters<T> = {

[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];

};

interface Person {

name: string;

age: number;

}

type PersonGetters = Getters<Person>;

// Result: { getName: () => string; getAge: () => number; }

Type Guards and Narrowing

// User-defined type guards

interface Bird { fly(): void; layEggs(): void; }

interface Fish { swim(): void; layEggs(): void; }

function isFish(pet: Fish | Bird): pet is Fish {

return (pet as Fish).swim !== undefined;

}

// Type predicates with generics

function isNotNull<T>(value: T | null): value is T {

return value !== null;

}

// Discriminated unions

type Result<T, E> =

| { success: true; data: T }

| { success: false; error: E };

function processResult<T, E>(result: Result<T, E>) {

if (result.success) {

console.log(result.data); // T

} else {

console.error(result.error); // E

}

}

// Assertion functions

function assertIsDefined<T>(value: T | undefined): asserts value is T {

if (value === undefined) {

throw new Error('Value is undefined');

}

}

Utility Types and Patterns

Advanced Utility Types

// Deep partial type

type DeepPartial<T> = T extends object ? {

[P in keyof T]?: DeepPartial<T[P]>;

} : T;

// Deep readonly type

type DeepReadonly<T> = T extends primitive ? T : {

readonly [P in keyof T]: DeepReadonly<T[P]>;

};

// Union to intersection

type UnionToIntersection<U> =

(U extends any ? (k: U) => void : never) extends

((k: infer I) => void) ? I : never;

// Flatten object type

type Flatten<T> = T extends object ? {

[K in keyof T]: T[K];

} : T;

Builder Pattern with Types

class QueryBuilder<T = {}> {

private query: T;

constructor(query: T = {} as T) {

this.query = query;

}

select<K extends string>(fields: K[]): QueryBuilder<T & { select: K[] }> {

return new QueryBuilder({ ...this.query, select: fields });

}

where<K extends string, V>(field: K, value: V): QueryBuilder<T & { where: { [key in K]: V } }> {

return new QueryBuilder({ ...this.query, where: { [field]: value } as any });

}

build(): T {

return this.query;

}

}

// Type-safe builder usage

const query = new QueryBuilder()

.select(['id', 'name'])

.where('status', 'active')

.build();

// Type: { select: string[]; where: { status: string } }

Template Literal Types

// Event handler types

type EventHandler<T extends string> = `on${Capitalize<T>}`;

type ClickHandler = EventHandler<'click'>; // "onClick"

// CSS unit types

type CSSUnit = 'px' | 'em' | 'rem' | '%';

type CSSValue = `${number}${CSSUnit}`;

// Route parameter extraction

type ExtractRouteParams<T extends string> =

T extends `${infer Start}/:${infer Param}/${infer Rest}`

? { [K in Param | keyof ExtractRouteParams<Rest>]: string }

: T extends `${infer Start}/:${infer Param}`

? { [K in Param]: string }

: {};

type UserRoute = ExtractRouteParams<'/users/:id/posts/:postId'>;

// Result: { id: string; postId: string }

Best Practices

Use Unknown Over Any

Prefer 'unknown' type over 'any' for type safety. Unknown requires type checking before use.

Strict Configuration

Enable strict mode in tsconfig.json for maximum type safety benefits.

Type Inference

Let TypeScript infer types when possible. Explicit types are only needed when inference isn't sufficient.

Published on 2024-08-31 • Category: Programming

← Back to Blog

NarvikHub

Free online developer tools and utilities for encoding, formatting, generating, and analyzing data. No registration required - all tools work directly in your browser.

Built for developers, by developers. Privacy-focused and open source.

Popular Tools

Base64 Encoder/DecoderJSON FormatterURL Encoder/DecoderHTML FormatterHash GeneratorUUID Generator

Blog Articles

Base64 Encoding GuideURL Encoding Deep DiveUnderstanding JWT TokensRegular Expressions GuideView All Articles →

Developer Tools & Utilities

Base64 Encoder/DecoderJSON FormatterURL Encoder/DecoderHTML FormatterHash GeneratorUUID GeneratorQR Code GeneratorJWT DecoderTimestamp ConverterRegex TesterText Diff CheckerHex ConverterImage Base64 ConverterASN.1 DecoderCharles Keygen

Free online tools for Base64 encoding, JSON formatting, URL encoding, hash generation, UUID creation, QR codes, JWT decoding, timestamp conversion, regex testing, and more.

Privacy PolicyTerms of ServiceContact

© 2024 NarvikHub. All rights reserved.