TypeScript中类型映射的使用
作者:海阔天空BM
1. 简介
映射就是将一种类型按照映射规则,转成另一种类型,通常用于对象类型。
这里类型B通过A采用属性名索引的写法,完成了类型B的定义
type A = { foo: number; bar: number; }; type B = { [prop in keyof A]: string; };
这里复制了一个一样的类型,类型B
原样复制了类型A
type A = { foo: number; bar: string; }; type B = { [prop in keyof A]: A[prop]; };
为了增加代码复用性,可以把常用的映射写成泛型。
这里定义了一个泛型,可以将其他对象的所有属性值都改成 boolean 类型。
type ToBoolean<Type> = { [Property in keyof Type]: boolean; };
不使用联合类型,直接使用某种具体类型进行属性名映射,也是可以的。
type MyObj = { [p in 'foo']: number; }; // 等同于 type MyObj = { foo: number; };
上面示例中,p in 'foo'
可以看成只有一个成员的联合类型,因此得到了只有这一个属性的对象类型。
通过映射,可以把某个对象的所有属性改成可选属性。比如ts 的内置工具类型Partial<T>
,就是这样实现的。
type A = { a: string; b: number; }; type B = { [Prop in keyof A]?: A[Prop]; };
上面示例中,类型B
在类型A
的所有属性名后面添加问号,使得这些属性都变成了可选属性。
ts内置的工具类型Readonly<T>
可以将所有属性改为只读属性,实现也是通过映射。
// 将 T 的所有属性改为只读属性 type Readonly<T> = { readonly [P in keyof T]: T[P]; }; // 用法如下。 type T = { a: string; b: number }; type ReadonlyT = Readonly<T>; // { // readonly a: string; // readonly b: number; // }
2. 映射修饰符
映射会原样复制原始对象的可选属性和只读属性,如果想要删除可选和只读这两个特性,并不太方便,所以为了解决这个问题,ts引入了两个修饰符,用来移除映射时添加或移除可选属性或者只读属性。
+
修饰符:写成+?
或+readonly
,为映射属性添加?
修饰符或readonly
修饰符。–
修饰符:写成-?
或-readonly
,为映射属性移除?
修饰符或readonly
修饰符。
这里添加、移除了可选属性,+?
或-?
要写在属性名的后面
// 添加可选属性 type Optional<Type> = { [Prop in keyof Type]+?: Type[Prop]; }; // 移除可选属性 type Concrete<Type> = { [Prop in keyof Type]-?: Type[Prop]; };
这里添加、移除只读属性,+readonly
和-readonly
要写在属性名的前面。
// 添加 readonly type CreateImmutable<Type> = { +readonly [Prop in keyof Type]: Type[Prop]; }; // 移除 readonly type CreateMutable<Type> = { -readonly [Prop in keyof Type]: Type[Prop]; };
如果同时增删?
和readonly
这两个修饰符,写成下面这样。
// 增加 type MyObj<T> = { +readonly [P in keyof T]+?: T[P]; }; // 移除 type MyObj<T> = { -readonly [P in keyof T]-?: T[P]; }
ts 原生的工具类型Required<T>
专门移除可选属性,就是使用-?
修饰符实现的。
另外,–?
修饰符移除了可选属性以后,该属性就不能等于undefined
了,实际变成必选属性了。但是,这个修饰符不会移除null
类型。
另外,+?
修饰符可以简写成?
,+readonly
修饰符可以简写成readonly
。
3. 键名重映射
1. 语法
ts4.1引入了键名重映射,允许改变键名,就是在键名映射的后面加上as +新类型字句,新类型字句一般是模板字符串,用来对原键名的操作。
type A = { foo: number; bar: number; }; type B = { [p in keyof A as `${p}ID`]: number; }; // 等同于 type B = { fooID: number; barID: number; };
上面示例中,类型B
是类型A
的映射,但在映射时把属性名改掉了,在原始属性名后面加上了字符串ID
。
可以看到,键名重映射的语法是在键名映射的后面加上as + 新类型
子句。这里的“新类型”通常是一个模板字符串,里面可以对原始键名进行各种操作。
2. 属性过滤
键名重映射可以过滤某些属性。
3. 联合类型的映射
因为键名重映射可以修改键名类型,所以原始键名的类型不必是string|number|symbol
,任意的联合类型都可以用来进行键名重映射。
type S = { kind: 'square', x: number, y: number, }; type C = { kind: 'circle', radius: number, }; type MyEvents<Events extends { kind: string }> = { [E in Events as E['kind']]: (event: E) => void; } type Config = MyEvents<S|C>; // 等同于 type Config = { square: (event:S) => void; circle: (event:C) => void; }
上面示例中,原始键名的映射是E in Events
,这里的Events
是两个对象组成的联合类型S|C
。所以,E
是一个对象,然后再通过键名重映射,得到字符串键名E['kind']
。
到此这篇关于TypeScript中类型映射的使用的文章就介绍到这了,更多相关TypeScript 类型映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!