条件类型
SomeType extends OtherType ? TrueType : FalseType
ts
// SomeType 是否是 OtherType 的子类型
type t1 = 1 extends number ? true : false; // true
type t2 = "1" extends number ? true : false; // false
type t3 = string extends object ? true : false; // false
type t4 = string extends Object ? true : false; // true
type t5 = { a: 1 } extends object ? true : false; // true
type t6 = { a: 1; b: 2 } extends { a: 1 } ? true : false; // true,结构化类型
type t7 = { a: 1 } extends { a: 1; b: 2 } ? true : false; // false
type t71 = 1 | 2 extends 1 | 2 | 3 ? true : false; // true
type t72 = 1 | 2 | 3 extends 1 | 2 ? true : false; // false
type t8 = string extends {} ? true : false; // true
type t9 = {} extends object ? true : false; // true
type t10 = object extends {} ? true : false; // true
type t11 = {} extends Object ? true : false; // true
type t12 = Object extends {} ? true : false; // true
type t13 = object extends Object ? true : false; // true
type t14 = Object extends object ? true : false; // true
// 原始类型的子面量类型 < 原始类型 < 原始类型对应的装箱类型 < Object
type t15 = string extends any ? true : false; // true
type t16 = Object extends any ? true : false; // true
type t17 = Object extends unknown ? true : false; // true
type t18 = any extends Object ? 1 : 2; // 1 | 2
type t19 = any extends "hello" ? 1 : 2; // 1 | 2
type t20 = unknown extends any ? true : false; // true
type t21 = any extends unknown ? true : false; // true判断类型之间的兼容性
ts
// 判断类型是否是字符串
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
type C = IsString<"hello">; // false
/**
* 实现一个IF 类型工具,真返回T,否则返回F
*/
type IF<C extends boolean, T, F> = C extends true ? T : F;
type D = IF<true, 1, 2>; // 1
type E = IF<false, string, number>; // number
/**
* 泛型约束:限定传入obj 必须有length属性
*/
type ObjLength = {
length: number;
};
function getObj<T extends ObjLength>(obj: T) {
return obj;
}
getObj(123); // error
getObj("hello"); // hello
/**
* 检测对象是否有message属性
*/
type Message<T> = T extends { message: unknown } ? T["message"] : never;
const person = {
id: 1,
};
type Message2 = Message<typeof person>; // never
/**
* 提取具体的类型
*/
type Flatten<T> = T extends any[] ? T[number] : T;
type Flatten<T> = T extends (infer U)[] ? U : T;
type Str = Flatten<string[]>; // string
type Str2 = Flatten<string>; // stringts
/**
* 条件嵌套
*/
// 实现类型工具Merge
type Foo = {
name: string;
age: string;
};
type Bar = {
age: number;
sex: string;
};
type Merge<T, U> = {
[P in keyof T | keyof U]: P extends keyof T
? T[P]
: P extends keyof U
? U[P]
: never;
};
type FooBar = Merge<Foo, Bar>; // { name: string; age: string; sex: string; }infer 关键字进行类型推断
ts
/**
* 提取具体的类型
*/
type Flatten<T> = T extends any[] ? T[number] : T;
// 优化,infer U 相当于any
type Flatten<T> = T extends (infer U)[] ? U : T;
type Str = Flatten<string[]>; // string
type Str2 = Flatten<string>; // stringts
type Arr1 = ["a", "b", "c"];
type Arr2 = [1, 2, 3];
type First<T extends any[]> = T extends [] ? never : T[0];
/**
* 提取第一个/最后一个类型
*/
type First<T extends any[]> = T extends [infer F, ...infer R] ? F : never;
type Last<T extends any[]> = T extends [...infer F, infer R] ? R : never;ts
// 将元组元素位置交换
type Swap<T extends any[]> = T extends [infer F, infer L] ? [L, F] : T;
type S1 = Swap<["a", "b", "c"]>; // ["a", "b", "c"]
type S2 = Swap<[1, 2]>; // [2, 1]
// 将数组倒序
type Reverse<T extends any[]> = T extends [...infer F, infer L]
? [L, ...Reverse<F>]
: [];
type R1 = Reverse<["a", "b", "c"]>; // ["c", "b", "a"]ts
// 获取函数返回类型
type MyReturnType<T extends (...args: any) => any> = T extends () => infer R
? R
: never;
// 官方工具:ReturnType<T>联合类型的分布式特性
必须满足三个条件
- 条件类型
- 联合类型
- 泛型
ts
type MyInclude<T, K> = T extends K ? T : never;
// 普通类型
type A = MyInclude<"hello", string>; // "hello"
// 联合类型:提炼
type B = MyInclude<"hello" | "world", string>; // "hello" | "world"
/* */
type C = "a" | "b" | "c";
type D = "a" | "b";
type E = MyInclude<C, D>; // "a" | "b"
/* 解析:MyInclude<C, D>
MyInclude<"a", "a" | "b"> // "a"
MyInclude<"b", "a" | "b"> // "b"
MyInclude<"c", "a" | "b"> // never
*/
/* */
// 类似:排除
type MyExclude<T, K> = T extends K ? never : T;
type MyOmit<T, K> = Pick<T, Exclude<keyof T, K>>;
/* */
// 官方工具
// Extract<T, K>
// Exclude<T, Kts
// 1. 编写一个类型工具,把部份键名设置为可选
// 使用 type newType = OptionalPick<User, "email" | "password">;
type User = {
name: string;
age: number;
email: string;
password: string;
isAdmin: boolean;
};
//
// Omit Pick Partial
// type RequiredPick = Omit<User, "email" | "password">; // name | age | isAdmin
// type PartialPick = Partial<Pick<User, "email" | "password">>; // 提取键名email | password,然后设置为可选
//
type OptionalPick<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// usage
const user: OptionalPick<User, "email" | "password"> = {
name: "zhangsan";
age: 18;
isAdmin: true;
};ts
// 分布式特性小问题,泛型参数不能被包裹
type ABB<T> = T extends any ? T[] : never;
type ACC<T> = [T] extends any ? T[] : never;
//
type A = ABB<string | number>; // string[] | number[]
type B = ACC<string | number>; // (string | number)[]