- Object 操作
- IfEquals
(是否相等) - WriteableKeys
(可写的key) - ReadonlyKeys
(只读的key) - RequiredKeys
(必选的key) - OptionalKeys
(可选的key) - Optional
(部分可选) - PickByValue
(根据value过滤) - PickByValueExact
- OmitByValue
(反向PickByValue) - Instersection
(交集) - Diff
(差集) - Overwrite
(重写) - Assign
(强制重写) - ValuesType
- Unionize
(重组联合) - Mutable
(转换只读) - MutableKeys
(只读的key) - ArgumentsRequired
(参数必选)
- IfEquals
- 其他操作
这里的工具类是 【utility-types】的源码。
Object 操作
IfEquals(是否相等)
用于判断两个类型是否相等。
export type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <
T
>() => T extends Y ? 1 : 2
? A
: B
如果你了解一些 TS 的话可能会想到,判断两个类型是否相同不是直接使用双向 extends 就可以了吗,这个是什么玩意?
我想你说的双向 extends 方式是这样的。
type Same<X, Y> = X extends Y ? (Y extends X ? true : false) : false
对于上面 Same 类型函数这种写法,其实是有缺陷的,它没有办法推断两个类型是否绝对相同,比如说相同结构但带有不同属性修饰符的对象类型。
type X = {
name: string
age: number
}
type Y = {
readonly name: string
age: number
}
上面这两个类型 Same 类型函数就无法推断,这种情况下就必须要使用IfEquals
类型函数了。
type SameResult = Same<X, Y> //true
type IfEqualsResult = IfEquals<X, Y> //never
WriteableKeys(可写的key)
用于获取对象类型中所有可写的 key。
源码:
export type WriteableKeys<T extends object> = {
[P in keyof T]-?: IfEquals<
{ [Q in P]: T[P] },
{ -readonly [Q in P]: T[P] },
P
>
}[keyof T];
示例:
type Props = { readonly foo: string; bar: number }
type WriteableKeysResult = WriteableKeys<Props> // "bar"
ReadonlyKeys(只读的key)
用于获取对象中所有 readonly 的key。
源码:
export type ReadonlyKeys<T extends object> = {
[P in keyof T]-?: IfEquals<
{ [Q in P]: T[P] },
{ -readonly [Q in P]: T[P] },
never,
P
>
}[keyof T]
示例:
type Props = { readonly foo: string; bar: number }
type ReadonlyKeysResult = ReadonlyKeys<Props> // "foo"
RequiredKeys(必选的key)
用于获取对象中所有必选的key。
源码:
export type RequiredKeys<T extends object> = {
[P in keyof T]-?: {} extends Pick<T, P> ? never : P
}[keyof T]
示例:
interface Props {
age: number;
name?: string;
}
type Demo = RequiredKeys<Props> // type Demo = 'age'
OptionalKeys(可选的key)
用于获取对象中所有可选的key。
源码:
export type OptionalKeys<T extends object> = {
[P in keyof T]-?: {} extends Pick<T, P> ? P : never
}[keyof T]
示例:
interface Props {
age: number;
name?: string;
}
type Demo = OptionalKeys<Props> // type Demo = 'name'
Optional(部分可选)
接收两个泛型参数,T和K,K是T所有key的子集,并将T中兼容的K属性转换为可选。
源码:
export type Optional<
T extends object,
K extends keyof T = keyof T,
I = Omit<T, K> & Partial<Pick<T, K>>
> = Pick<I, keyof I>
示例:
type Props = {
name: string;
age: number;
}
type Demo = Optional<Props, 'name'>
// type Demo = {name?: string; age: number}
PickByValue(根据value过滤)
根据value的类型,来过滤对象的key。
源码:
export type PickByValue<T, K> = Pick<
T,
{
[P in keyof T]-?: T[P] extends K ? P : never
}[keyof T]
>
示例:
interface Props {
age: number;
name?: string;
color: string;
}
type Demo = PickByValue<Props, string> // type Demo = { color: string }
上面的代码中,只过滤了必选的。
PickByValueExact
嗯,是 PickByValue 的严格版。
export type PickByValueExact<T, K> = Pick<
T,
{
[P in keyof T]-?: IfEquals<[K], [T[P]], P>
}[keyof T]
>
OmitByValue(反向PickByValue)
反向根据value过滤。
源码:
export type OmitByValue<T, U> = Pick<
T,
{
[P in keyof T]: T[P] extends U ? never : P
}[keyof T]
>
示例:
interface Props {
age: number;
color: string;
}
type Demo = OmitByValue<Props, number>
// type Demo = { color: string }
Instersection(交集)
获取两个对象中的交集。
源码:
export type Intersection<T extends object, U extends object> = Pick<
T,
Extract<keyof T, keyof U> & Extract<keyof U, keyof T>
>
示例:
type Props1 = {
name: string
age: number
visible: boolean
sex: string | number
}
type Props2 = {
age: number;
color: string;
type: boolean;
}
type Demo = Intersection<Props1, Props2> // type Demo = {age: number}
Diff(差集)
同 Instersection 相反。
export type Diff<T extends object, U extends object> = Pick<
T,
Exclude<keyof T, keyof U>
>
示例:
type Props1 = {
name: string
age: number
visible: boolean
sex: string | number
}
type Props2 = {
age: number;
}
type Demo = Diff<Props1, Props2>
// type Demo = {name: string; visible: boolean; sex: string | number;}
Overwrite(重写)
接收两个参数,A和B。B的属性类型会覆盖A的属性类型。
源码:
export type Overwrite<
T extends object,
U extends Object,
I = Diff<T, U> & Intersection<U, T>
> = Pick<I, keyof I>
示例:
type Props = {
name: string;
age: number;
}
type Props2 = {
age: string;
}
type Demo = Overwrite<Props, Props2>
// type Demo = {name: string; age: string}
Assign(强制重写)
比 Overwrite 更强大一些,当B中有A不存在的属性时,会添加到A对象中。
源码:
export type Assign<
T extends object,
U extends object,
I = Diff<T, U> & Intersection<U, T> & Diff<U, T>
> = Pick<I, keyof I>
示例:
type Props = {
name: string;
age: number;
}
type Props2 = {
color: string;
}
type Demo = Assign<Props, Props2>
// type Demo = {name: string; age: number; color: string;}
ValuesType
接收一个泛型参数,返回值的联合类型。如果是数组的话,返回其中的子元素。
源码:
export type ValuesType<
T extends Array<any> | ReadonlyArray<any> | ArrayLike<any> | object
> = T extends Array<any> | ReadonlyArray<any> | ArrayLike<any>
? T[number]
: T extends object
? T[keyof T]
: never
示例:
type Props = {
name: string;
age: number;
}
type Demo = ValuesType<Props>
// type Demo = string | number;
type Props2 = Array<{
name: string;
age: number;
}>
type Demo2 = ValuesType<Props2>
// type Demo2 = {name: string; age: number;}
Unionize(重组联合)
接收一个对象,返回一个转为单独key对象的联合类型。
源码:
export type Unionize<T extends object> = {
[P in keyof T]: { [Q in P]: T[P] }
}[keyof T]
示例:
type Props = { name: string; age: number; visible: boolean }
type UnionizeResult = Unionize<Props>
// {
// name: string;
// } | {
// age: number;
// } | {
// visible: boolean;
// }
Mutable (转换只读)
将对象中所有只读的属性转换为非只读类型。
源码:
export type Mutable<T> = { -readonly [P in keyof T]: T[P] };
示例:
type Demo = Mutable<{readonly age: number}>
// type Demo = {age: number}
MutableKeys (只读的key)
用于获取对象中所有非只读属性的key。
源码:
export type MutableKeys<T extends object> = {
[P in keyof T]-?: IfEquals<
{ [Q in P]: T[P] },
{ -readonly [Q in P]: T[P] },
P
>;
}[keyof T];
示例:
type Demo = MutableKeys<{age: number, readonly color: string, name: string}>
// type Demo = 'age' | 'name';
ArgumentsRequired(参数必选)
用于将泛型的参数都转换为必选。
源码:
export type ArgumentsRequired<
T extends object,
K extends keyof T = keyof T,
I = Omit<T, K> & Required<Pick<T, K>>
> = Pick<I, keyof I>
示例:
type Props = {
name?: string;
age?: number;
}
type Demo = ArgumentsRequired<Props>
// type Demo = {name: string; age: number;}
其他操作
Unionize(转联合)
用于将一个对象转换为联合类型。
源码:
export type Unionize<T extends object> = {
[P in keyof T]: { [Q in P]: T[P] }
}[keyof T]
示例:
type Props = { name: string; age: number; visible: boolean };
// Expect: { name: string; } | { age: number; } | { visible: boolean; }
type UnionizedType = Unionize<Props>;
ReturnType(返回类型)
获取函数类型的返回类型。
interface Props{
age: number;
name: string;
}
type getUrl = (url: string) => Props;
type Demo = ReturnType<getUrl> // type Demo = Props;
InstanceType
获取构造函数函数类型的返回类型,有些类似 ConstructorParameters。
type E = InstanceType<ErrorConstructor>; // type F = Error
type F = InstanceType<FunctionConstructor>; // type F = Function
Parameters(函数参数)
用于获得当前函数参数类型,组成的数组。
type A = Parameters<() => void>; // []
type B = Parameters<typeof Array.isArray>; // [any]
type C = Parameters<typeof parseInt>; // [string, (number | undefined)?]
type D = Parameters<typeof Math.max>; // number[]
type getUrl = (url: string, options: IProps) => string;
type Demo = Parameters<getUrl>;
// type Demo = [url: string, options: IProps];
PromiseType
用于返回Promise泛型的类型。
源码:
export type PromiseType<T extends Promise<unknown>> = T extends Promise<infer V>
? V
: never
示例:
type PromiseTypeResult = PromiseType<Promise<string>>
// string
TupleToUnion(元组转联合)
将一个元组(数组)类型转换为一个联合类型。
源码:
export type TupleToUnion<T extends any[]> = T extends Array<infer U> ? U : never
示例:
type Demo = TupleToUnion<[string, number]>
// type Demo = string | number;
UnionToIntersection(联合转交集)
用于将一个联合类型转换为一个交叉类型。
源码:
export type UnionToIntersection<T> = (T extends any
? (arg: T) => void
: never) extends (arg: infer V) => void
? V
: never
示例:
type Demo = UnionToIntersection<
{ name: string } | { age: number } | { visible: boolean }
>
// type Demo = { name: string } & { age: number } & { visible: boolean }
// 又或者 { name: string; age: number; visible: boolean }