TypeScript 面向高级的十大技巧

101 阅读3分钟

1. 使用keyof和映射类型动态构建类型:与映射类型相结合,您可以从现有类型生成新类型,同时保留原始结构。


type User = { name: '张三', age: 0 }
type NullLabelUser = { [K in keyof User]: User[K] | null }

// 这里的NullabelUser 成为一种新类型,具有与相同的键User,但具有可为空的值

2. Exclude 排除指定类型: TypeScript 提供了一个内置 Exclude实用类型,用于从联合类型中排除指定类型。

type User = { name: '张三', age: 0, nickName: '小三' }
type Exclude<T, U> = T extends U ? never : T
type Ex = Exclude<keyof User, 'name'>

//  例子中,Ex 结果  Ex = "age" | "nickName" 忽略 User 原始类型中的 name 属性 

3. 灵活类型的条件类型。条件类型允许创建依赖于其他类型的复杂类型。这可以带来更灵活和可重用的类型定义。

type Flatten<T> = T extends Array<infer U> ? U : T
type FlattenedNumbers = Flatten<number[]>

// 例子中,Flatten类型检查提供的类型T是否为数组,如果是,它会提取内部类型U。

4. 带有柯里化的部分应用类型,TypeScript 对高阶类型的支持允许创建部分应用的类型。这种技术成为类型柯里化,可以实现强大的组合模式。

type Curried<T, U> = (arg: U) => T & U
function merge<T, U>(fun: Curried<T, U>): T & U {
  return fn({} as T)
}
type UserDatails = { firsName: string, lastName: string }
type UserSettings = { theme: string; language: string }
const result = merge<UserDatails, UserSettings>(() => ({
  firstName: 'John',
  lastName: 'Doe',
  theme: 'dark',
  language: 'en',
}))

5. 用于编译时类型检查的类型保护:当您需要在执行编译时类型检查时,类型保护非常有用。他们允许 TypeScript 缩小特定代码中值的类型范围。

function isString(val: any): value is string {
  return typeof value === 'string'
}
function check(a: unknown, b: unknown) {
  if (isString(a) && isString(b)) {
    return a.check(b)
  }
}
// 在concat函数中,TypeScript知道由于类型保护是String,a和b是字符串。
// 这还可以改善您来自VS Code Intellisense的提示,因为编译器将能够约束任何类型。

6. 高级类型推断:实用程序 Returntype 类型可以推断函数的返回类型,从而更容易使用高阶函数及其类型

type MyFunction = (x: number, y: number) => { result: number; }
type MyFunctionReturnType = ReturnType<MyFunction>

//  例子中,MyFunctionReturnType成为MyFunction的推断返回类型。

7. 使用递归类型进行类型级编程:TypeScript 支持递归类型,允许您创建复杂的类型级计算和转化。

type MyFunction = (x: number, y: number) => { result: number; }
type MyFunctionReturnType = ReturnType<MyFunction>

//  例子中,MyFunctionReturnType成为MyFunction的推断返回类型。

8. Readonly 只读属性: TypeScript 提供了一个内置 Readonly 实用程序类型,可以使对象的所有属性变为只读。当您想要在代码库中强制执行不变性时,这非常有用。

type User = { name: string; age: number };
type Rea = Readonly<User>
const user: ReadonlyUser = { name: "Alice", age: 30 };

9. 类型断言已实现更多控制:当您对值的类型的了解比 TypeScript 的类型推断所能推断的更多时,类型断言非常有用。它们允许您为值指定更精确的类型,而无需执行任何运行时检查。

const unknownValue: unknown = "hello world";
const stringValue: string = unknownValue as string;

// 例子中,我们断言unknownValue确实是一个字符串,TypeScript将信任此断言。

10. 更安全的常数的特殊符号:TypeScript 的 unique symbol 类型可以创建唯一的非字符串值,非常适合更安全的常量定义并避免名称冲突。

const MyConstant = Symbol("MyConstant") as unique symbol;
type MyType = {
  [MyConstant]: string;
};
const obj: MyType = { [MyConstant]: "hellow world!" };
obj[MyConstant] // hellow world!

// 在这里,MyConstant是一个独特的符号,确保没有其他属性可以与它碰撞。