輔助工具類型
- 對(duì)于交叉類型的結(jié)構(gòu)恍风,F(xiàn)latten 能夠?qū)⑺蛊綖閱螌拥膶?duì)象結(jié)構(gòu)
type Flatten<T> = { [K in keyof T]: T[K] };
屬性修飾類型工具
- 深度可選參數(shù)
type DeepPartial<T extends object> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
- 深度必選參數(shù)
type DeepRequired<T extends object> = {
[K in keyof T]-?: T[K] extends object ? DeepRequired<T[K]> : T[K];
};
- 深度只讀參數(shù)
// 也可以記作 DeepImmutable
type DeepReadonly<T extends object> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
- 深度可變參數(shù)
type DeepMutable<T extends object> = {
-readonly [K in keyof T]: T[K] extends object ? DeepMutable<T[K]> : T[K];
};
- 從聯(lián)合類型剔除
null | undefined
- 在開啟
--strictNullChecks
下才能正常工作蹦狂。
- 在開啟
type NonNullable<T> = T extends null | undefined ? never : T;
type DeepNonNullable<T extends object> = {
[K in keyof T]: T[K] extends object
? DeepNonNullable<T[K]>
: NonNullable<T[K]>;
};
基于部分屬性修飾的類型工具
- 拆分對(duì)象結(jié)構(gòu),那不就是內(nèi)置工具類型一節(jié)中講到的結(jié)構(gòu)工具類型朋贬,即 Pick 與 Omit凯楔?
- 三個(gè)屬性的對(duì)象全部變?yōu)榭蛇x,那不就是屬性修飾锦募?豈不是可以直接用上面剛學(xué)到的遞歸屬性修飾摆屯?
- 組合兩個(gè)對(duì)象類型,也就意味著得到一個(gè)同時(shí)符合這兩個(gè)對(duì)象類型的新結(jié)構(gòu)糠亩,那不就是交叉類型虐骑?
- 將一個(gè)對(duì)象的部分屬性標(biāo)記為可選
/**
* T: 需要處理的對(duì)象類型
* K: 需要標(biāo)記為可選的屬性, 必須為 T 內(nèi)部的屬性, 對(duì)象屬性組成的字面量聯(lián)合類型
*/
type MarkPropsAsOptional<
T extends object,
K extends keyof T = keyof T
> = Flatten<Partial<Pick<T, K>> & Omit<T, K>>;
type MarkPropsAsOptionalStruct = MarkPropsAsOptional<
{
foo: string;
bar: number;
baz: boolean;
},
"bar"
>;
- 將一個(gè)對(duì)象的部分屬性標(biāo)記為必須
type MarkPropsAsRequired<
T extends object,
K extends keyof T = keyof T
> = Flatten<Omit<T, K> & Required<Pick<T, K>>>;
- 將一個(gè)對(duì)象的部分屬性標(biāo)記為只讀
type MarkPropsAsReadonly<
T extends object,
K extends keyof T = keyof T
> = Flatten<Omit<T, K> & Readonly<Pick<T, K>>>;
- 將一個(gè)對(duì)象的部分屬性不只讀(可變)
type MarkPropsAsMutable<
T extends object,
K extends keyof T = keyof T
> = Flatten<Omit<T, K> & Mutable<Pick<T, K>>>;
- 講一個(gè)對(duì)象的部分屬性剔除
null | undefined
type MarkPropsAsNonNullable<
T extends object,
K extends keyof T = keyof T
> = Flatten<Omit<T, K> & NonNullable<Pick<T, K>>>;
結(jié)構(gòu)工具
- 基于期望的類型去拿到所有此類型的屬性名, Pick 出所有函數(shù)類型的值
type FuncStruct = (...args: any[]) => any;
type FunctionKeys<T extends object> = {
[K in keyof T]: T[K] extends FuncStruct ? K : never;
}[keyof T];
// 對(duì)上面的解釋
type Tmp<T extends object> = {
[K in keyof T]: T[K] extends FuncStruct ? K : never;
};
type Res = Tmp<{
foo: () => void;
bar: () => number;
baz: number;
}>;
type ResEqual = {
foo: 'foo';
bar: 'bar';
baz: never;
};
type WhatWeWillGet = Res[keyof Res]; // 'foo' | 'bar'
type WhatWillWeGetEqual1 = Res["foo" | "bar" | "baz"];
type WhatWillWeGetEqual2 = Res["foo"] | Res["bar"] | Res["baz"];
type WhatWillWeGetEqual3 = "foo" | "bar" | never;
- 基于鍵值類型查找屬性, 將預(yù)期類型也作為泛型參數(shù)
// 我們預(yù)期查找的類型, 第二個(gè)參數(shù)
type ExpectedPropKeys<T extends object, valueType> = {
[Key in keyof T]-?: T[Key] extends valueType ? Key : never;
}[keyof T];
type PickByValueType<T extends object, valueType> = Pick<
T,
ExpectedPropKeys<T, valueType>
>;
// {
// foo: string;
// }
type PickResult1 = PickByValueType<{ foo: string; bar: number }, string>;
// {
// foo: string;
// bar: number;
// }
type PickResult2 = PickByValueType<
{ foo: string; bar: number; baz: boolean },
string | number
>;
// OmitByValueType 也是類似的,我們只需要一個(gè)和 ExpectedPropKeys 作用相反的工具類型即可赎线,比如來(lái)個(gè) FilteredPropKeys廷没,只需要調(diào)換條件類型語(yǔ)句結(jié)果的兩端
type FilteredPropKeys<T extends object, ValueType> = {
[Key in keyof T]-?: T[Key] extends ValueType ? never : Key;
}[keyof T];
type OmitByValueType<T extends object, ValueType> = Pick<
T,
FilteredPropKeys<T, ValueType>
>;
type OmitRes1 = OmitByValueType<{ foo: string; bar: number }, string>;
type OmitRes2 = OmitByValueType<
{ foo: string; bar: number; baz: boolean },
string | number
>;
集合工具
// 一維
// 并集
type Concurrence<A, B> = A | B
// 交集
type Intersection<A, B> = A extends B ? A : never
// 差集
type Difference<A, B> = A extends B ? never : A
// 補(bǔ)集
type Complement<A, B extends A> = Difference<A, B>
- 屬性名并集
// 實(shí)現(xiàn)對(duì)象屬性名的版本
type PlainObjectType = Record<string, any>;
// 屬性名并集
type ObjectKeysConcurrence<
T extends PlainObjectType,
U extends PlainObjectType
> = keyof T | keyof U;
- 屬性名交集
// 屬性名交集
type ObjectKeysIntersection<
T extends PlainObjectType,
U extends PlainObjectType
> = Intersection<keyof T, keyof U>;
- 屬性名差集
// 屬性名差集
export type ObjectKeysDifference<
T extends PlainObjectType,
U extends PlainObjectType
> = Difference<keyof T, keyof U>;
- 屬性名補(bǔ)集
// 屬性名補(bǔ)集
export type ObjectKeysComplement<
T extends U,
U extends PlainObjectType
> = Complement<keyof T, keyof U>;
- 提取首個(gè)參數(shù)類型
type FunctionType = (...args: any) => any;
type FirstParameter<T extends FunctionType> = T extends (
arg: infer P,
...args: any
) => any
? P
: never;
- 提取最后一個(gè)參數(shù)
type FunctionType = (...args: any) => any;
type LastParameter<T extends FunctionType> = T extends (arg: infer P) => any
? P
: T extends (...args: infer R) => any
? R extends [...any, infer Q]
? Q
: never
: never;
type FuncFoo = (arg: number) => void;
type FuncBar = (...args: string[]) => void;
type FuncBaz = (arg1: string, arg2: boolean) => void;
type FooLastParameter = LastParameter<FuncFoo>; // number
type BarLastParameter = LastParameter<FuncBar>; // string
type BazLastParameter = LastParameter<FuncBaz>; // boolean
- 提取 Promise 內(nèi)部值類型的工具類型 PromiseValue
// 首先提取到 then 方法中的函數(shù)類型,再通過(guò)這個(gè)函數(shù)類型的首個(gè)參數(shù)來(lái)提取出實(shí)際的值垂寥。
type Awaited<T> = T extends null | undefined
? T
: T extends object & { then(onfulfilled: infer F): any }
? F extends (value: infer V, ...args: any) => any
? Awaited<V>
: never
: T;