TypeScript 中的高级类型操作:深入理解 UnionKeysUniqueLeft 类型

在 TypeScript 中,类型操作是构建灵活且安全代码的重要工具。这里展示的代码通过高级类型定义实现了对联合类型和差异类型的提取。这段代码定义了三个类型:UnionKeysUniqueLeftKeysUniqueLeft。它们分别完成了一些特定的类型计算任务,以下通过逐个分析的方式详细说明。

代码解析与每个 token 的意义

// 定义联合类型的键

type UnionKeys<T, U> = keyof T | keyof U;

这行代码的作用是提取两个类型 TU 的键并将它们联合。它利用了 keyof 操作符,该操作符用于提取对象类型的键并返回一个联合类型。

关键点:

  1. type 定义一个类型别名。
  2. UnionKeys<T, U> 是泛型类型,它接受两个泛型参数 TU
  3. keyof T 表示获取类型 T 的所有键。
  4. keyof T | keyof U 将类型 T 和类型 U 的所有键取并集。

示例:

type A = { a: number; b: string };
type B = { b: string; c: boolean };
type Result = UnionKeys<A, B>; // 结果: "a" | "b" | "c"

在这里,Result 类型表示联合类型 "a" | "b" | "c"

接下来定义了 UniqueLeftKeys 类型:

/**
 * Get unique keys of left type.
 */
type UniqueLeftKeys<T, U> = Exclude<UnionKeys<T, U>, keyof U>;

此类型用于计算类型 T 中存在但不在类型 U 中的键。

  1. type UniqueLeftKeys<T, U> 是一个泛型类型,接受两个参数。
  2. UnionKeys<T, U> 表示 TU 键的并集。
  3. keyof U 表示类型 U 的键。
  4. Exclude<A, B> 是 TypeScript 内置类型,用于从类型 A 中排除 B 的所有成员。

示例:

type UniqueKeys = UniqueLeftKeys<A, B>; // 结果: "a"

在此示例中,键 "a" 存在于类型 A 中,但不在类型 B 中。

接下来定义了 UniqueLeft 类型:

/**
 * Extract left-only types.
 */
type UniqueLeft<T, U> = {
  [P in UniqueLeftKeys<T, U>]: T[P];
};

这个类型用于提取类型 T 中那些键仅存在于 T 中的键值对。

  1. type UniqueLeft<T, U> 是一个泛型类型。
  2. { [P in UniqueLeftKeys<T, U>]: T[P] } 是映射类型,用于从 T 中提取 UniqueLeftKeys<T, U> 的键并保持其值的类型。
  3. [P in UniqueLeftKeys<T, U>] 表示迭代 UniqueLeftKeys<T, U> 中的每个键。
  4. T[P] 表示从 T 类型中获取键 P 对应的值类型。

示例:

type LeftOnly = UniqueLeft<A, B>; // 结果: { a: number }

在这个例子中,LeftOnly 类型提取了仅存在于类型 A 中的键值对,结果是 { a: number }

运行示例的完整代码

以下是一段可以运行的完整 TypeScript 代码:

type UnionKeys<T, U> = keyof T | keyof U;

type UniqueLeftKeys<T, U> = Exclude<UnionKeys<T, U>, keyof U>;

type UniqueLeft<T, U> = {
  [P in UniqueLeftKeys<T, U>]: T[P];
};

type A = { a: number; b: string };
type B = { b: string; c: boolean };

type Union = UnionKeys<A, B>; // `a` | `b` | `c`
type LeftKeys = UniqueLeftKeys<A, B>; // `a`
type LeftOnly = UniqueLeft<A, B>; // { a: number }

const example: LeftOnly = {
  a: 42,
};

console.log(example); // { a: 42 }

类型操作的用途

这段代码的主要作用是:

  1. 比较两个类型之间的差异。
  2. 提取某些类型中独有的键值对。
  3. 在泛型上下文中处理复杂类型。

此类操作在构建强类型工具、类型验证和库开发中非常有用。