TypeScript高级特性与类型编程

深入理解TypeScript类型系统,掌握高级类型编程技巧

TypeScript高级特性详解

本文将深入介绍TypeScript的高级特性和类型编程技巧,帮助你更好地利用TypeScript的类型系统。

泛型高级用法

  1. 泛型约束
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 正确
loggingIdentity("hello");
loggingIdentity([1, 2, 3]);

// 错误
loggingIdentity(3); // 数字没有length属性
  1. 泛型工具类型
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Partial - 使所有属性可选
interface Todo {
    title: string;
    description: string;
}

type PartialTodo = Partial<Todo>;
// 等同于
// {
//     title?: string;
//     description?: string;
// }

// Record - 构造键值对类型
type PageInfo = {
    title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
    home: { title: "Home" },
    about: { title: "About" },
    contact: { title: "Contact" }
};

高级类型

  1. 映射类型
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
}

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
}

// 使用示例
interface Person {
    name: string;
    age: number;
}

type ReadonlyPerson = Readonly<Person>;
type NameOnly = Pick<Person, "name">;
  1. 条件类型
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type NonNullable<T> = T extends null | undefined ? never : T;

// 使用示例
type T1 = NonNullable<string | number | undefined>;  // string | number
type T2 = NonNullable<string[] | null | undefined>;  // string[]

// 分布式条件类型
type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";

类型推断

  1. 类型推导
1
2
3
4
5
6
7
// 返回类型推导
function createPair<S, T>(v1: S, v2: T): [S, T] {
    return [v1, v2];
}

// TypeScript能够推导出返回类型
const pair = createPair("hello", 42); // [string, number]
  1. 类型保护
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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;
}

function getSmallPet(): Fish | Bird {
    // ...
    return {} as Fish | Bird;
}

let pet = getSmallPet();
if (isFish(pet)) {
    pet.swim();
} else {
    pet.fly();
}

装饰器

  1. 类装饰器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function classDecorator<T extends { new (...args: any[]): {} }>(
    constructor: T
) {
    return class extends constructor {
        newProperty = "new property";
        hello = "override";
    };
}

@classDecorator
class Greeter {
    property = "property";
    hello: string;
    constructor(m: string) {
        this.hello = m;
    }
}
  1. 方法装饰器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    let originalMethod = descriptor.value;
    
    descriptor.value = function(...args: any[]) {
        console.log(`Calling ${propertyKey} with`, args);
        return originalMethod.apply(this, args);
    };
    
    return descriptor;
}

class Calculator {
    @log
    add(x: number, y: number) {
        return x + y;
    }
}

高级实践

  1. 类型体操
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 递归类型
type DeepReadonly<T> = {
    readonly [P in keyof T]: T[P] extends object
        ? DeepReadonly<T[P]>
        : T[P];
}

// 联合转交叉
type UnionToIntersection<U> = 
    (U extends any ? (k: U) => void : never) extends
    ((k: infer I) => void) ? I : never;
  1. 工具类型实现
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 提取Promise返回类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

// 获取函数返回类型
type ReturnType<T extends (...args: any) => any> = 
    T extends (...args: any) => infer R ? R : any;

// 获取构造函数实例类型
type InstanceType<T extends new (...args: any) => any> = 
    T extends new (...args: any) => infer R ? R : any;

最佳实践

  1. 类型定义规范
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 使用interface定义对象类型
interface User {
    id: number;
    name: string;
    preferences?: UserPreferences;
}

// 使用type定义联合类型或工具类型
type ID = string | number;
type Nullable<T> = T | null;
  1. 类型断言最佳实践
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 优先使用as const
const config = {
    endpoint: "api.example.com",
    timeout: 3000
} as const;

// 避免使用any,使用unknown代替
function processValue(value: unknown) {
    if (typeof value === "string") {
        return value.toUpperCase();
    }
    return String(value);
}

掌握这些TypeScript高级特性,将帮助你写出更安全、可维护的TypeScript代码。

使用绝夜之城强力驱动