Skip to content

类型系统里的逻辑运算

extend: 条件运算

ts
type StringOrNumber<T> = T extends string ? "string" : "number";

infer: 提取操作

ts
// 提取函数参数类型
type GetParamsType<T> = T extends (...args: infer P) => any ? P : never;

// 提取返回类型
type GetReturnType<T> = T extends (...args: any) => infer R ? R : never;

// 提取数组内任意位置的值
type ExtractStartAndEnd<T extend any[]> = T extends [infer A, ...any[], infer B] ? [A, B] : T;
type Swap<T extends any[]> = T extends [infer A, infer B] ? [B, A] : [T]
type ArrayItemType<T> = T extends Array<infer ElementType> ? ElementType : never;

// 作用于对象
type PropType<T, K extends keyof T> = T extends { [Key in K]: infer R } ? R : never;

// 作用于 Promise
type PromiseValue<T> = T extends Promise<infer V> ? V : T;
type PromiseValue2<T> = T extends Promise<infer V> ? promiseValue2<V> : T;

分布式条件类型

条件类型分布式起作用的条件:

  • 类型参数是联合类型
  • 类型参数通过泛型参数传入,不能直接进行条件判断
  • 泛型参数不能被包裹
typescript
type Condition<T> = T extends 1 | 2 | 3 ? T : never;

type Res1 = Condition<1 | 2 | 3 | 4 | 5>; // 1 | 2 | 3

type Naked<T> = T extends boolean ? "Y" : "N";
type Wrapped<T> = [T] extends [boolean] ? "Y" : "N";

type Res2 = Naked<number | boolean>; // 'N' | 'Y'

对于是否包裹的条件,使用数组包裹是其中一种,还可以用以下方式:

export type NoDistribute<T> = T & {}

判断 never 和 any 的方法

由于分布式条件类型的存在,我们需要一些 trick 去绕过它,进而判断 never 和 any

ts
type IsNver<T> = [T] extends [never] ? true : false;

type IsAny<T> = 0 extends 1 & T ? true : false; // 1 & any => any

// 满足 unknown extends T 的只有 any 和 unknown, 用于收窄类型
type IsUnknown<T> = unknown extends T
  ? IsAny<T> extends true
    ? false
    : true
  : false;
2025( )
今日 8.33%
本周 42.86%
本月 48.39%
本年 4.11%
Powered by Snowinlu | Copyright © 2024- | MIT License