Indexed Access Types 索引访问类型
可以使用索引访问类型来查找另一个类型上的特定属性:
type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
// 上面的类型等同于
type Age = number;
索引类型本身就是一个类型,所以我们可以使用union、keyof或其他类型:
type T1 = Person["age" | "name"];
// 等同于
type T1 = string | number
type T2 = Person[keyof Person];
// 等同于
type T2 = string | number | boolean;
type AliveOrName = "alive" | "name";
type T3 = Person[AliveName];
// 等同于
type T3 = string | boolean;
另一个使用任意类型进行索引的例子是使用number来获取数组元素的类型。可以将它与typeof结合起来,方便捕获数组字面量的元素类型:
const MyArray = [
{ name: 'Alice', age: 15 },
{ name: 'Bob', age: 23 },
{ name: 'Eve', age: 38 },
]
type Person = typeof MyArray[number]
// 等同于
// type Person = { name: string, age: number }
type Age = (typeof MyArray[number])['age']
// 等同于
type Age2 = Person['age'] // type Age2 = number
只能在索引时使用类型,这意味着你不能使用const来做变量引用:
const key = "age";
type Age = Person[key]; // 报错
// Type 'key' cannot be used as an index type.
// key不能被用作索引类型
// 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?
// “key”指的是一个值,但在这里被用作类型。你是说“typeof key”吗?
// 所以只需要做一点修改即可
type Age = Person[typeof key];
Awaited
该类型用于模拟async函数中的await操作,或者Promise上的.then()方法——具体来说,就是它们递归展开Promise的方式。
type A = Awaited<Promise<string>>;
// ^?
type B = Awaited<Promise<Promise<number>>>;
// ^?
type C = Awaited<boolean | Promise<number>>;
// ^?
Partial
type Partial<T> = {
[P in keyof T]?: T[P];
};
构造一个将type的所有属性设置为可选的类型。此实用程序将返回表示给定类型的所有子集的类型。
interface Todo {
title: string;
description: string;
}
// Partial<Todo> 得到的结果是
interface PartialTodo {
title?: string;
description?: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
title: "organize desk",
description: "clear clutter",
};
const todo2 = updateTodo(todo1, {
description: "throw out trash",
});
Required
type Required<T> = {
[P in keyof T]-?: T[P];
};
Partial的反义词。
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 };
// Required<Props> 得到的结果是
interface RequiredProps {
a: number;
b: string;
}
const obj2: Required<Props> = { a: 5 }; // 报错 Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
Readonly
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
将每个属性设置为只读属性,后期不可以更改
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
todo.title = "Hello"; // 报错 Cannot assign to 'title' because it is a read-only property.
Record
type Record<K extends keyof any, T> = {
[P in K]: T;
};
构造一个对象类型,其属性的key为Keys类型,属性值为Type类型。它可以将一个类型的属性映射到另一个类型。
type CatName = "miffy" | "boris" | "mordred";
interface CatInfo {
age: number;
breed: string;
}
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
cats.boris; // const cats: Record<CatName, CatInfo>
Pick 对象字段挑选类型
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
从Type中选出一组属性Keys(字符串字面量值或字符串字面量值的并集)来构造一个类型。
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
// 翻译过来就是
interface TodoPreviewPick {
title: string;
completed: boolean;
}
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
todo; // TodoPreview
Omit 对象字段排除类型
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
构造一个除类型K以外具有T属性的类型。与Pick相反。
interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
createdAt: 1615544252770,
};
todo; // TodoPreview
type TodoInfo = Omit<Todo, "completed" | "createdAt">;
const todoInfo: TodoInfo = {
title: "Pick up kids",
description: "Kindergarten closes at 5pm",
};
todoInfo; // TodoInfo
Exclude 联合补集类型
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
Exclude<UnionType, ExcludedMembers>,通过从UnionType中排除可分配给ExcludedMembers的所有联合成员来构造类型。
type T0 = Exclude<"a" | "b" | "c", "a">; // type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // type T1 = "c"
type T2 = Exclude<string | number | (() => void), Function>; // type T1 = string | number
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; x: number }
| { kind: "triangle"; x: number; y: number };
type T3 = Exclude<Shape, { kind: "circle" }>
// type T3 = { kind: "square"; x: number; } | { kind: "triangle"; x: number; y: number; }
Extract 联合相交类型
/**
* Extract from T those types that are assignable to U
* 从T中提取可赋值给U的类型
*/
type Extract<T, U> = T extends U ? T : never;
Extract<Type, Union>,通过从Type中提取可分配给Union的所有联合成员来构造类型。取相交的
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // type T0 = "a"
type T1 = Extract<string | number | (() => void), Function>; // type T1 = () => void
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; x: number }
| { kind: "triangle"; x: number; y: number };
type T2 = Extract<Shape, { kind: "circle" }>
// type T2 = { kind: "circle"; radius: number; }
NonNullable
/**
* Exclude null and undefined from T
* 从T类型中排除null和undefined类型
*/
type NonNullable<T> = T & {};
通过从Type中排除null和undefined来构造一个类型。
type T0 = NonNullable<string | number | undefined>; // type T0 = string | number
type T1 = NonNullable<string[] | null | undefined>; // type T1 = string[]
Parameters 函数参数类型
/**
* Obtain the parameters of a function type in a tuple
* 获取元组中函数类型的参数
*/
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
Parameters<Type>,从函数类型Type的形参中使用的类型构造元组类型。
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>; // type T0 = [] 没有参数,所以是空数组
type T1 = Parameters<(s: string) => void>; // type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>; // type T2 = [arg: unknown]
type T3 = Parameters<typeof f1>; // type T3 = [arg: { a: number; b: string; }]
typeof f1; // (arg: { a: number; b: string; }) => void
type T4 = Parameters<any>; // type T4 = unknown[]
type T5 = Parameters<never>; // type T5 = never
type T6 = Parameters<string>; // Type 'string' does not satisfy the constraint '(...args: any) => any'
type T7 = Parameters<Function>; // Type 'Function' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'.
ReturnType 函数返回值类型
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
得到函数的返回值类型
// @errors: 2344 2344
declare function f1(): { a: number; b: string };
type T0 = ReturnType<() => string>; // type T0 = string
type T1 = ReturnType<(s: string) => void>; // type T1 = void
type T2 = ReturnType<<T>() => T>; // type T2 = unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // type T3 = number[]
type T4 = ReturnType<typeof f1>; // type T4 = { a: number; b: string; }
type T5 = ReturnType<any>; // type T5 = any
type T6 = ReturnType<never>; // type T6 = never
type T7 = ReturnType<string>; // Type 'string' does not satisfy the constraint '(...args: any) => any'.
type T8 = ReturnType<Function>; // Type 'Function' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'.
TupleToUnion 元组转集合
实现范型TupleToUnion<T>,它返回元组所有值的集合。
例如:
type Arr = ['1', '2', '3']
type Test = TupleToUnion<Arr> // '1' | '2' | '3'
实现方式:
type Arr = ['1', '2', '3']
// 实现
type TupleToUnion<T extends any[]> = T[number]
type Test = TupleToUnion<Arr> // '1' | '2' | '3'
const test: Test = '1'
元组转对象
将一个元组类型转换为对象类型,这个对象类型的键/值和元组中的元素对应。
例如:
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple> // expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}