docs: finish chapter utility
This commit is contained in:
@@ -13,3 +13,5 @@
|
||||
- enum.md: Enum 类型
|
||||
- assert.md: 类型断言
|
||||
- operator.md: 运算符
|
||||
- mapping.md: 类型映射
|
||||
- utility.md: 类型工具
|
||||
|
||||
@@ -18,7 +18,7 @@ type B = {
|
||||
};
|
||||
```
|
||||
|
||||
上面示例中,这两个类型的属性结构是一样的,但是属性的类型不一样。如果属性数量多的话,写起来就很麻烦。
|
||||
上面示例中,这两个类型的属性结构是一样的,但是属性的类型不一样。如果属性数量多的话,逐个写起来就很麻烦。
|
||||
|
||||
使用类型映射,就可以从类型`A`得到类型`B`。
|
||||
|
||||
@@ -66,8 +66,6 @@ type ToBoolean<Type> = {
|
||||
|
||||
上面示例中,定义了一个泛型,可以将其他对象的所有属性值都改成 boolean 类型。
|
||||
|
||||
由于对象的属性名,只有 string、number、symbol 三种可能,所以 keyof 运算符返回的联合类型,应该是`string | number | symbol`的子类型。
|
||||
|
||||
下面是另一个例子。
|
||||
|
||||
```typescript
|
||||
@@ -145,12 +143,12 @@ type Readonly<T> = {
|
||||
|
||||
```typescript
|
||||
type T = { a: string; b: number };
|
||||
|
||||
// {
|
||||
|
||||
type ReadonlyT = Readonly<T>;
|
||||
// {
|
||||
// readonly a: string;
|
||||
// readonly b: number;
|
||||
// }
|
||||
type ReadonlyT = Readonly<T>;
|
||||
```
|
||||
|
||||
## 映射修饰符
|
||||
@@ -178,7 +176,7 @@ type B = {
|
||||
|
||||
如果要删改可选和只读这两个特性,并不是很方便。为了解决这个问题,TypeScript 引入了两个映射修饰符,用来在映射时添加或移除某个属性的`?`修饰符和`readonly`修饰符。
|
||||
|
||||
- `+`修饰符:写成`+?`或`+readonly`,为映射属性添加`?`修饰符或`readonly`修饰符。
|
||||
- `+`修饰符:写成`+?`或`+readonly`,为映射属性添加`?`修饰符或`readonly`修饰符。
|
||||
- `–`修饰符:写成`-?`或`-readonly`,为映射属性移除`?`修饰符或`readonly`修饰符。
|
||||
|
||||
下面是添加或移除可选属性的例子。
|
||||
@@ -248,7 +246,7 @@ type B<T> = {
|
||||
|
||||
### 语法
|
||||
|
||||
TypeScript 4.1 引入了键名重映射(key remapping),允许将键名指定为其他类型。
|
||||
TypeScript 4.1 引入了键名重映射(key remapping),允许改变键名。
|
||||
|
||||
```typescript
|
||||
type A = {
|
||||
@@ -281,12 +279,12 @@ interface Person {
|
||||
}
|
||||
|
||||
type Getters<T> = {
|
||||
[P in keyof T
|
||||
as `get${Capitalize<string & P>}`]: () => T[P];
|
||||
[P in keyof T
|
||||
as `get${Capitalize<string & P>}`]: () => T[P];
|
||||
};
|
||||
|
||||
|
||||
type LazyPerson = Getters<Person>;
|
||||
// 等同于
|
||||
// 等同于
|
||||
type LazyPerson = {
|
||||
getName: () => string;
|
||||
getAge: () => number;
|
||||
@@ -313,20 +311,20 @@ type User = {
|
||||
}
|
||||
|
||||
type Filter<T> = {
|
||||
[K in keyof T
|
||||
as T[K] extends string ? K : never]: string
|
||||
[K in keyof T
|
||||
as T[K] extends string ? K : never]: string
|
||||
}
|
||||
|
||||
type FilteredUser = Filter<User> // { name: string }
|
||||
```
|
||||
|
||||
上面示例中,映射`K in keyof T`获取类型`T`的每一个属性以后,然后使用`as Type`修改键名的类型。
|
||||
上面示例中,映射`K in keyof T`获取类型`T`的每一个属性以后,然后使用`as Type`修改键名。
|
||||
|
||||
它的键盘重映射`as T[K] extends string ? K : never]`,使用了条件运算符。如果属性值`T[K]`的类型是字符串,那么属性名不变,否则属性名类型改为`never`,即这个属性名不存在。这样就等于过滤了不符合条件的属性,只保留属性值为字符串的属性。
|
||||
它的键名重映射`as T[K] extends string ? K : never]`,使用了条件运算符。如果属性值`T[K]`的类型是字符串,那么属性名不变,否则属性名类型改为`never`,即这个属性名不存在。这样就等于过滤了不符合条件的属性,只保留属性值为字符串的属性。
|
||||
|
||||
### 联合类型的映射
|
||||
|
||||
由于键名重映射可以修改键名类型,所以原始键名的类型不必是`string|number|symbol`,任意的联合类型都可以。
|
||||
由于键名重映射可以修改键名类型,所以原始键名的类型不必是`string|number|symbol`,任意的联合类型都可以用来进行键名重映射。
|
||||
|
||||
```typescript
|
||||
type S = {
|
||||
@@ -340,7 +338,7 @@ type C = {
|
||||
radius: number,
|
||||
};
|
||||
|
||||
type MyEvents<Eevnts extends { kind: string }> = {
|
||||
type MyEvents<Events extends { kind: string }> = {
|
||||
[E in Events as E['kind']]: (event: E) => void;
|
||||
}
|
||||
|
||||
@@ -357,3 +355,4 @@ type Config = {
|
||||
## 参考链接
|
||||
|
||||
- [Mapped Type Modifiers in TypeScript](https://mariusschulz.com/blog/mapped-type-modifiers-in-typescript), Marius Schulz
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ type C = Awaited<boolean | Promise<number>>;
|
||||
`Awaited<Type>`的实现如下。
|
||||
|
||||
```typescript
|
||||
type Awaited<T> =
|
||||
type Awaited<T> =
|
||||
T extends null | undefined ? T :
|
||||
T extends object & {
|
||||
then(
|
||||
@@ -56,7 +56,7 @@ type Awaited<T> =
|
||||
type T1 = ConstructorParameters<
|
||||
new (x: string, y: number) => object
|
||||
>; // [x: string, y: number]
|
||||
|
||||
|
||||
type T2 = ConstructorParameters<
|
||||
new (x?: string) => object
|
||||
>; // [x?: string | undefined]
|
||||
@@ -88,7 +88,7 @@ type T2 = ConstructorParameters<Function>; // 报错
|
||||
|
||||
`any`类型和`never`类型是两个特殊值,分别返回`unknown[]`和`never`。
|
||||
|
||||
```typescript
|
||||
```typescript
|
||||
type T1 = ConstructorParameters<any>; // unknown[]
|
||||
|
||||
type T2 = ConstructorParameters<never>; // never
|
||||
@@ -262,12 +262,14 @@ function toHex(this: Number) {
|
||||
type T = OmitThisParameter<typeof toHex>; // () => string
|
||||
```
|
||||
|
||||
上面示例中,`OmitThisParameter<T>`给出了函数`toHex()`的类型,并将其中的`this`参数删除。
|
||||
|
||||
如果函数没有 this 参数,则返回原始函数类型。
|
||||
|
||||
`OmitThisParameter<Type>`的实现如下。
|
||||
|
||||
```typescript
|
||||
type OmitThisParameter<T> =
|
||||
type OmitThisParameter<T> =
|
||||
unknown extends ThisParameterType<T> ? T :
|
||||
T extends (...args: infer A) => infer R ?
|
||||
(...args: A) => R : T;
|
||||
@@ -281,7 +283,7 @@ type OmitThisParameter<T> =
|
||||
type T1 = Parameters<() => string>; // []
|
||||
|
||||
type T2 = Parameters<(s:string) => void>; // [s:string]
|
||||
|
||||
|
||||
type T3 = Parameters<<T>(arg: T) => T>; // [arg: unknown]
|
||||
|
||||
type T4 = Parameters<
|
||||
@@ -459,7 +461,7 @@ interface Person {
|
||||
age: number;
|
||||
}
|
||||
|
||||
const worker: Readonly<Partial<Person>>
|
||||
const worker: Readonly<Partial<Person>>
|
||||
= { name: '张三' };
|
||||
|
||||
worker.name = '李四'; // 报错
|
||||
@@ -605,7 +607,7 @@ type T2 = ReturnType<never>; // never
|
||||
```typescript
|
||||
type ReturnType<
|
||||
T extends (...args: any) => any
|
||||
> =
|
||||
> =
|
||||
T extends (...args: any) => infer R ? R : any;
|
||||
```
|
||||
|
||||
@@ -644,7 +646,7 @@ interface HelperThisValue {
|
||||
|
||||
let helperFunctions:
|
||||
{ [name: string]: Function } &
|
||||
ThisType<HelperThisValue>
|
||||
ThisType<HelperThisValue>
|
||||
= {
|
||||
hello: function() {
|
||||
this.logError("Error: Something wrong!"); // 正确
|
||||
@@ -662,7 +664,7 @@ let helperFunctions:
|
||||
下面是另一个例子。
|
||||
|
||||
```typescript
|
||||
let obj: ThisType<{ x: number }> &
|
||||
let obj: ThisType<{ x: number }> &
|
||||
{ getX: () => number };
|
||||
|
||||
obj = {
|
||||
@@ -734,10 +736,11 @@ type A = 'HELLO';
|
||||
|
||||
// "hELLO"
|
||||
type B = Uncapitalize<A>;
|
||||
```
|
||||
```
|
||||
|
||||
上面示例中,`Uncapitalize<T>`将 HELLO 转为 hELLO。
|
||||
|
||||
## 参考链接
|
||||
|
||||
- [What is TypeScript's ThisType used for?](https://stackoverflow.com/questions/55029032/what-is-typescripts-thistype-used-for)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user