Record<K, T>
在打字稿中是什么意思?
Typescript 2.1引入了Record
类型,并在一个示例中进行了描述:
// For every properties K of type T, transform it to U function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>
Advanced Types页在“映射类型”标题下的Record
,Readonly
和Partial
旁边提到了Pick
,其定义如下:
type Record<K extends string, T> = { [P in K]: T; }
Readonly,Partial和Pick是同态的,而Record不是同态的。记录不是同态的一个线索是它不需要输入类型来复制以下属性:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
就是这样。除以上引用外,在typescriptlang.org上没有其他提及Record
。
有人可以简单说明Record
是什么吗?
Record<K,T>
只是一种说法“此对象上的所有属性都将具有类型T
”的一种方式吗?可能不是全部属性,因为K
具有某些用途...
K
泛型是否在对象上禁止非K
的其他键,或者是否允许它们并且仅指示其属性未转换为T
?
以给出的示例为例:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
与它完全相同吗?:
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
答案 0 :(得分:68)
- 有人可以简单地定义
Record
是什么吗?
Record<K, T>
是一种对象类型,其属性键为K
,其属性值为T
。也就是说,keyof Record<K, T>
等效于K
,Record<K, T>[K]
(基本上)等效于T
。
Record<K,T>
只是一种说法“此对象上的所有属性都将具有类型T
”的一种方式吗?可能不是所有对象,因为K
具有某些用途...
您注意到,K
的目的是……将属性键限制为特定值。如果要接受所有可能的字符串值键,则可以执行类似Record<string, T>
的操作,但是惯用的方法是使用{ [k: string]: T }
之类的index signature。
K
泛型是否在对象上禁止使用非K
的其他键,或者是否允许它们并且仅指示其属性未转换为T
?
它并不完全“禁止”其他键:毕竟,通常允许一个值具有其类型中未明确提及的属性...但是它无法识别此类属性的存在:
declare const x: Record<"a", string>;
x.b; // error, Property 'b' does not exist on type 'Record<"a", string>'
,它会将它们视为excess properties,有时会被拒绝:
declare function acceptR(x: Record<"a", string>): void;
acceptR({a: "hey", b: "you"}); // error, Object literal may only specify known properties
有时被接受:
const y = {a: "hey", b: "you"};
acceptR(y); // okay
以给出的示例为例:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
与它完全相同吗?:
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
是的!
希望有帮助。祝你好运!
答案 1 :(得分:9)
记录使您可以从联合创建新类型。 Union中的值用作新类型的属性。
例如,说我有一个像这样的联合会:
type CatNames = "miffy" | "boris" | "mordred";
现在,我想创建一个包含所有猫的信息的对象,我可以使用CatName Union中的值作为键来创建新类型。
type CatList = Record<CatNames, {age: number}>
如果要满足此CatList,必须创建一个这样的对象:
const cats:CatList = {
miffy: { age:99 },
boris: { age:16 },
mordred: { age:600 }
}
您将获得非常强大的类型安全性:
我最近用它来创建一个Status组件。该组件将收到状态道具,然后呈现一个图标。为了说明起见,我在这里简化了很多代码
我有一个这样的工会:
type Statuses = "failed" | "complete";
我用它来创建这样的对象:
const icons: Record<
Statuses,
{ iconType: IconTypes; iconColor: IconColors }
> = {
failed: {
iconType: "warning",
iconColor: "red"
},
complete: {
iconType: "check",
iconColor: "green"
};
然后我可以通过将对象中的元素分解为道具来进行渲染,如下所示:
const Status = ({status}) => <Icon {...icons[status]} />
如果以后扩展或更改状态联合,我知道我的状态组件将无法编译,并且会得到一个错误,可以立即修复。这使我可以向应用程序添加其他错误状态。
请注意,实际的应用程序具有在多个位置引用的数十种错误状态,因此这种类型的安全性非常有用。