type-manipulation 类型操作
# 目录
# Generics 泛型
- Generic Types:泛型类型
We can also write the generic type as a call signature of an object literal type: 我们也可以将泛型类型写作为对象文本类型的调用签名:
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: { <Type>(arg: Type): Type } = identity;
2
3
4
5
- Generic Classes: 泛型类
A class has two sides to its type: the static side and the instance side. Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class’s type parameter. 类的类型有两个方面:静态方面和实例方面。泛型类只是泛型的实例端而不是静态端,因此在处理类时,静态成员不能使用类的类型参数。
Generic Constraints: 泛型约束
Using Type Parameters in Generic Constraints:在泛型约束中使用类型参数
Using Class Types in Generics:在泛型中使用类类型
# Keyof Type Operator 类型操作运算符
If the type has a string or number index signature, keyof will return those types instead: 如果类型有字符串或数字索引签名,keyof 将返回这些类型:
type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish;
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
2
3
4
5
# Typeof Type Operator
it’s only legal to use typeof on identifiers (i.e. variable names) or their properties. 使用 typeof on 标识符 (即变量名) 或其属性是合法的
# Indexed Access Types
The indexing type is itself a type, so we can use unions, keyof, or other types entirely: 索引类型本身是一种类型,因此我们可以使用联合、键或其他类型:
type I1 = Person["age" | "name"];
type I2 = Person[keyof Person];
2
Another example of indexing with an arbitrary type is using number to get the type of an array’s elements. We can combine this with typeof to conveniently capture the element type of an array literal: 使用任意类型进行索引的另一个示例是使用 number 来获取数组元素的类型。我们可以把它和 typeof 结合起来,方便地捕获数组文字的元素类型:
const MyArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
type Age = typeof MyArray[number]["age"];
2
3
4
5
6
# Conditional Types 条件类型
type NameOrId<T extends number | string> = T extends number
? IdLabel
: NameLabel;
2
3
- Conditional Type Constraints 条件类型约束
type MessageOf<T extends { message: unknown }> = T["message"];
type Flatten<T> = T extends any[] ? T[number] : T;
2
- Inferring Within Conditional Types 在条件类型中推断
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
2
3
4
5
- Distributive Conditional Types: 分配条件类型
When conditional types act on a generic type, they become distributive when given a union type. 当条件类型作用于泛型类型时,它们在给定联合类型时成为分配类型。
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>; // type StrArrOrNumArr = string[] | number[]
2
3
Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the extends keyword with square brackets. 通常,分布性是期望的行为。为了避免这种行为,可以用方括号将 extends 关键字的每一边包围起来。
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
// 'StrArrOrNumArr' is no longer a union.
type StrArrOrNumArr = ToArrayNonDist<string | number>; //type StrArrOrNumArr = (string | number)[]
2
3
4
# Mapped Types 映射类型
Mapped types build on the syntax for index signatures, which are used to declare the types of properties which have not been declared ahead of time: 映射类型建立在索引签名的语法之上,索引签名用于声明未提前声明的属性类型:
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
2
3
4
5
6
7
- Mapping Modifiers: 映射修饰符
There are two additional modifiers which can be applied during mapping: readonly and ? which affect mutability and optionality respectively. 在映射过程中可以使用两个额外的修饰符: readonly 和?,它们分别影响可变性和可选性。
You can remove or add these modifiers by prefixing with - or +. If you don’t add a prefix, then + is assumed. 您可以通过使用 - 或 + 作为前缀来删除或添加这些修饰符。如果您没有添加前缀,则假定为 + 。
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type Concrete<Type> = {
[Property in keyof Type]-?: Type[Property];
};
2
3
4
5
6
- Key Remapping via as
In TypeScript 4.1 and onwards, you can re-map keys in mapped types with an as clause in a mapped type: 在 TypeScript 4.1 及以后的版本中,您可以使用映射类型中的 as 子句重新映射映射类型的键:
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
// type LazyPerson = {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }
type LazyPerson = Getters<Person>;
type RemoveKindField<Type> = {
[Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
You can map over arbitrary unions, not just unions of string | number | symbol, but unions of any type: 你可以映射任意的联合,不仅仅是字符串 | 数字 | 符号的联合,而是任意类型的联合:
type EventConfig<Events extends { kind: string }> = {
[E in Events as E["kind"]]: (event: E) => void;
}
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
// type Config = {
// square: (event: SquareEvent) => void;
// circle: (event: CircleEvent) => void;
// }
type Config = EventConfig<SquareEvent | CircleEvent>
2
3
4
5
6
7
8
9
10
11
# Template Literal Types 模板文字类型
- String Unions in Types 类型字符串联合
type PropEventSource<Type> = {
on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void;
};
/// Create a "watched object" with an 'on' method
/// so that you can watch for changes to properties.
declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;
2
3
4
5
6
7
- Inference with Template Literals: 使用模板文字进行推理
type PropEventSource<Type> = {
on<Key extends string & keyof Type>
(eventName: `${Key}Changed`, callback: (newValue: Type[Key]) => void ): void;
};
2
3
4
- Intrinsic String Manipulation Types: 内部字符串操作类型
To help with string manipulation, TypeScript includes a set of types which can be used in string manipulation. These types come built-in to the compiler for performance and can’t be found in the .d.ts files included with TypeScript.
为了帮助进行字符串操作,TypeScript 包含了一组可用于字符串操作的类型。这些类型是编译器内置的,用于提高性能,在。打字稿中包含的 d.ts 文件。
Uppercase<StringType>
: Converts each character in the string to the uppercase version. 将字符串中的每个字符转换为大写版本。
Lowercase<StringType>
: Converts each character in the string to the lowercase equivalent. 将字符串中的每个字符转换为等效的小写形式。
Capitalize<StringType>
: Converts the first character in the string to an uppercase equivalent. 将字符串中的第一个字符转换为等效的大写字母。
Uncapitalize<StringType>
: Converts the first character in the string to a lowercase equivalent. 将字符串中的第一个字符转换为等效的小写形式。