chengaofeng
发布于 2024-07-25 / 14 阅读
0
0

Typescript类型体操

TypeScript 的类型体操(TypeScript Type Manipulation)是指通过类型系统进行复杂的类型操作和推断,以实现更灵活和强大的类型检查。

in keyof

跟 for ... in 相似,不过 in keyof 是用来操作类型的

interface Person {
  name: string;
  age: number;
  location: string;
}

// 使用 keyof 获取对象的所有键
type PersonKeys = keyof Person; // 'name' | 'age' | 'location'
// 使用 keyof 获取对象的所有值
type PersonValues = Person[PersonKeys]; // string | number
// 使用 in keyof 获取对象的所有键值对
type PersonEntries = {
  [K in PersonKeys]: Person[K];
};
// 封装通用工具
type GenericEntries<T> = {
  [K in keyof T]: T[K];
};
type PersonEntries2 = GenericEntries<Person>;

Vue3源码中的类型体操

export type UnwrapRef<T> = T extends Ref<infer V>
  ? UnwrapRefSimple<V>
  : UnwrapRefSimple<T>;

type UnwrapRefSimple<T> = T extends
  | Function
  | CollectioinTypes
  | BaseTypes
  | Ref
  | RefUnwrapBailType[keyof RefUnwrapBailTypes]
  ? T
  : T extends Array<any>
  ? {
      [K in keyof T]: UnwrapRefSimple<T[K]>;
    }
  : T extends object
  ? UnwrappedObject<T>
  : T;

代码解释

export type UnwrapRef<T> = T extends Ref<infer V>

  ? UnwrapRefSimple<V>

  : UnwrapRefSimple<T>;

UnwrapRef 是一个类型别名,用于解包 Ref 类型。如果 TRef 类型,则提取其内部类型 V 并递归调用 UnwrapRefSimple。否则,直接调用 UnwrapRefSimple

type UnwrapRefSimple<T> = T extends

  | Function

  | CollectioinTypes

  | BaseTypes

  | Ref

  | RefUnwrapBailType[keyof RefUnwrapBailTypes]

  ? T

  : T extends Array<any>

  ? {

      [K in keyof T]: UnwrapRefSimple<T[K]>;

    }

  : T extends object

  ? UnwrappedObject<T>

  : T;

UnwrapRefSimple 是一个类型别名,用于处理不同类型的解包逻辑:

  1. 基本类型检查

    T extends | Function | CollectioinTypes | BaseTypes | Ref | RefUnwrapBailType[keyof RefUnwrapBailTypes]

    如果 TFunctionCollectioinTypesBaseTypesRefRefUnwrapBailType 的某个键的类型,则直接返回 T

  2. 数组类型处理

    T extends Array<any>

    如果 T 是数组类型,则递归解包数组的每个元素:

    {
    
      [K in keyof T]: UnwrapRefSimple<T[K]>;
    
    }
  3. 对象类型处理

    T extends object

    如果 T 是对象类型,则调用 UnwrappedObject<T> 进行解包。

  4. 其他类型: 如果 T 不符合上述任何一种情况,则直接返回 T

类型体操的应用

类型体操在 TypeScript 中非常有用,特别是在以下场景中:

  1. 类型推断:通过条件类型和 infer 关键字,可以从复杂类型中提取子类型。

  2. 类型转换:将一种类型转换为另一种类型,例如将联合类型转换为交叉类型。

  3. 类型保护:通过类型守卫和类型谓词,确保代码在运行时的类型安全。

  4. 类型映射:使用映射类型(如 keyof 和索引签名)来操作对象和数组类型。

示例

以下是一个简单的类型体操示例,用于提取函数的返回类型:

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

function exampleFunction(): string {

  return "Hello, TypeScript!";

}

type ExampleReturnType = ReturnType<typeof exampleFunction>; // ExampleReturnType = string

通过理解和掌握类型体操,你可以编写更强大和灵活的 TypeScript 代码,提高代码的类型安全性和可维护性。


评论