TypeScript 的类型体操(Type Manipulation)

54 阅读2分钟

TypeScript 的类型体操(Type Manipulation)是指使用 TypeScript 的类型系统来操作和转换类型,从而实现更灵活和强大的类型定义。这包括使用泛型、联合类型、交叉类型、条件类型等等。以下是一些常见的类型体操示例:

1. 泛型 (Generics)

泛型允许您创建可重用的组件,这些组件可以在多个类型中工作。

function identity<T>(arg: T): T {
    return arg;
}

let output = identity<string>("hello"); // 输出: string
console.log(output);

2. 联合类型 (Union Types)

联合类型允许一个变量可以是多种类型之一。

function padLeft(value: string, padding: number | string): string {
    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}`);
}

console.log(padLeft("Hello", 4));   // 输出: "    Hello"
console.log(padLeft("Hello", "   ")); // 输出: "   Hello"

3. 交叉类型 (Intersection Types)

交叉类型允许将多个类型合并为一个类型。

interface BusinessPartner {
    name: string;
    credit: number;
}

interface Identity {
    id: number;
    email: string;
}

type Employee = BusinessPartner & Identity;

let employee: Employee = {
    name: "John Doe",
    credit: 1000,
    id: 123,
    email: "john.doe@example.com"
};

console.log(employee.name); // 输出: John Doe
console.log(employee.id);   // 输出: 123

4. 条件类型 (Conditional Types)

条件类型允许根据类型是否满足某些条件来选择不同的类型。

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

type StringOrNumber = NonNullable<string | number | null>; // 输出: string | number
type StringOrUndefined = NonNullable<string | undefined>; // 输出: string

5. 映射类型 (Mapped Types)

映射类型允许您基于现有的类型创建一个新的类型。

type ReadOnly<T> = {
    [P in keyof T]: T[P];
};

interface User {
    name: string;
    age: number;
}

type ReadOnlyUser = ReadOnly<User>;

const user: ReadOnlyUser = {
    name: "Alice",
    age: 30
};

// user.name = "Bob"; // 错误: Cannot assign to 'name' because it is a read-only property.

6. 索引签名 (Index Signatures)

索引签名允许您创建具有动态属性的类型。

interface StringMap {
    [key: string]: string;
}

const stringMap: StringMap = {
    name: "Alice",
    city: "New York"
};

console.log(stringMap.name); // 输出: Alice

7. typeof 和 keyof 操作符

typeof 操作符用于获取变量的类型,keyof 操作符用于获取对象的所有键的联合类型。

const obj = { a: 1, b: "hello" };
type ObjType = typeof obj; // 输出: { a: number; b: string; }
type Keys = keyof ObjType; // 输出: "a" | "b"

console.log(Keys); // 输出: "a" | "b"

8. infer 关键字

infer 关键字用于在条件类型中推断类型。

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

type PromiseString = ExtractPromiseValue<Promise<string>>; // 输出: string
type NotPromise = ExtractPromiseValue<number>; // 输出: never

这些只是 TypeScript 中类型体操的一些基本示例。通过结合使用这些功能,您可以创建非常复杂和强大的类型系统,以满足各种开发需求。