Home >Web Front-end >JS Tutorial >Advanced TypeScript: A Deep Dive into Modern TypeScript Development
TypeScript has become the go-to language for building scalable JavaScript applications. In this comprehensive guide, we'll explore advanced TypeScript concepts that will enhance your development skills and help you write more type-safe code.
Understanding complex type relationships:
type IsArray<T> = T extends any[] ? true : false; type IsString<T> = T extends string ? true : false; // Usage type CheckArray = IsArray<string[]>; // true type CheckString = IsString<"hello">; // true // More complex conditional types type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; type ArrayElement<T> = T extends (infer U)[] ? U : never; // Example usage type PromiseString = UnwrapPromise<Promise<string>>; // string type NumberArray = ArrayElement<number[]>; // number
Leveraging string literal types for better type safety:
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'; type APIEndpoint = '/users' | '/posts' | '/comments'; type APIRoute = `${HTTPMethod} ${APIEndpoint}`; // Valid routes const validRoute: APIRoute = 'GET /users'; const validRoute2: APIRoute = 'POST /posts'; // Error: Type '"PATCH /users"' is not assignable to type 'APIRoute' // const invalidRoute: APIRoute = 'PATCH /users'; // Dynamic template literal types type PropEventType<T extends string> = `on${Capitalize<T>}`; type ButtonEvents = PropEventType<'click' | 'hover' | 'focus'>; // Results in: 'onClick' | 'onHover' | 'onFocus'
Creating flexible yet type-safe generic interfaces:
interface Database<T extends { id: string }> { find(id: string): Promise<T | null>; create(data: Omit<T, 'id'>): Promise<T>; update(id: string, data: Partial<T>): Promise<T>; delete(id: string): Promise<boolean>; } // Implementation example class MongoDatabase<T extends { id: string }> implements Database<T> { constructor(private collection: string) {} async find(id: string): Promise<T | null> { // Implementation return null; } async create(data: Omit<T, 'id'>): Promise<T> { // Implementation return { id: 'generated', ...data } as T; } async update(id: string, data: Partial<T>): Promise<T> { // Implementation return { id, ...data } as T; } async delete(id: string): Promise<boolean> { // Implementation return true; } }
Advanced type transformations:
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] }; interface Person { name: string; age: number; } type PersonGetters = Getters<Person>; // Results in: // { // getName: () => string; // getAge: () => number; // } // Advanced key remapping with filtering type FilteredKeys<T, U> = { [K in keyof T as T[K] extends U ? K : never]: T[K] }; interface Mixed { name: string; count: number; isActive: boolean; data: object; } type StringKeys = FilteredKeys<Mixed, string>; // Results in: { name: string }
Creating powerful metadata-driven decorators:
function ValidateProperty(validationFn: (value: any) => boolean) { return function (target: any, propertyKey: string) { let value: any; const getter = function() { return value; }; const setter = function(newVal: any) { if (!validationFn(newVal)) { throw new Error(`Invalid value for ${propertyKey}`); } value = newVal; }; Object.defineProperty(target, propertyKey, { get: getter, set: setter, enumerable: true, configurable: true, }); }; } class User { @ValidateProperty((value) => typeof value === 'string' && value.length > 0) name: string; @ValidateProperty((value) => typeof value === 'number' && value >= 0) age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } }
Building powerful type transformations:
// Deep Partial type type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; }; // Deep Required type type DeepRequired<T> = { [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P]; }; // Deep Readonly type type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]; }; // Example usage interface Config { server: { port: number; host: string; options: { timeout: number; retries: number; }; }; database: { url: string; name: string; }; } type PartialConfig = DeepPartial<Config>; // Now we can have partial nested objects const config: PartialConfig = { server: { port: 3000 // host and options can be omitted } };
Implementing the builder pattern with full type safety:
class RequestBuilder<T = {}> { private data: T; constructor(data: T = {} as T) { this.data = data; } with<K extends string, V>( key: K, value: V ): RequestBuilder<T & { [key in K]: V }> { return new RequestBuilder({ ...this.data, [key]: value, }); } build(): T { return this.data; } } // Usage const request = new RequestBuilder() .with('url', 'https://api.example.com') .with('method', 'GET') .with('headers', { 'Content-Type': 'application/json' }) .build(); // Type is inferred correctly type Request = typeof request; // { // url: string; // method: string; // headers: { 'Content-Type': string }; // }
Creating a robust error handling system:
class Result<T, E extends Error> { private constructor( private value: T | null, private error: E | null ) {} static ok<T>(value: T): Result<T, never> { return new Result(value, null); } static err<E extends Error>(error: E): Result<never, E> { return new Result(null, error); } map<U>(fn: (value: T) => U): Result<U, E> { if (this.value === null) { return new Result(null, this.error); } return new Result(fn(this.value), null); } mapError<F extends Error>(fn: (error: E) => F): Result<T, F> { if (this.error === null) { return new Result(this.value, null); } return new Result(null, fn(this.error)); } unwrap(): T { if (this.value === null) { throw this.error; } return this.value; } } // Usage example function divide(a: number, b: number): Result<number, Error> { if (b === 0) { return Result.err(new Error('Division by zero')); } return Result.ok(a / b); } const result = divide(10, 2) .map(n => n * 2) .unwrap(); // 10
These advanced TypeScript patterns demonstrate the language's power in creating type-safe and maintainable applications. By mastering these concepts, you'll be better equipped to build robust applications that leverage TypeScript's type system to its fullest potential.
TypeScript Documentation
TypeScript Deep Dive
TypeScript GitHub Repository
Share your experiences with these patterns in the comments below! What advanced TypeScript features have you found most useful in your projects?
Tags: #typescript #javascript #webdevelopment #programming #typing
The above is the detailed content of Advanced TypeScript: A Deep Dive into Modern TypeScript Development. For more information, please follow other related articles on the PHP Chinese website!