请考虑以下TypeScript代码:
'use strict';
type Value = 1 | 2 ;
type Owner = 'ownerA' | 'ownerB';
type ItemType = 'itemTypeA' | 'itemTypeB';
type Item = {
type: ItemType;
owner: Owner;
value: Value;
};
type AnotherType = {
[k in keyof Item]: null | {
[m in keyof Item[k]]: number;
};
};
const v: AnotherType = {
type: { itemTypeA: 0, itemTypeB: 1,},
owner: { ownerA: 0, ownerB: 1,},
value: null,
};
console.log(v);
字符串
在这种情况下,tsc
抛出一个错误:
错误TS 2322:类型'{ itemTypeA:number; itemTypeB:number; }”不能分配给类型“{ [x:number]:number; toString:number; charAt:number; charCodeAt:编号; concat:number; indexOf:number; lastIndexOf:number; localeCompare:...
显然,由于某种原因,[m in keyof Item[k]]: number;
迭代包含了不可枚举的,甚至是不存在的属性(不确定对象类型是否可以继承自Object.prototype的类型),比如:charCodeAt、charAt等
据我所知,这与'keyof'类型操作符的文档相矛盾,它被描述为:
keyof运算符接受一个对象类型,并生成其键的字符串或数字字面值联合。下面的类型P与类型P =“x”是同一类型|“y”:type Point = { x: number; y: number }; type P = keyof Point;
即,不存在“charAt”等。值,只有'x'和'y'。
可能与in
运算符有关,但同样,在JS中,它只遍历对象的可枚举属性(不确定在TypeScript中,当它用作类型运算符时是否如此)。
有没有人能解释一下,这是怎么回事?
1条答案
按热度按时间7ivaypg91#
你应该把你的类型改成类似
字符串
在嵌套的mapped type中不使用
keyof
运算符。M in keyof Item[K]
的问题是Item[K]
是Item
接口中的indexed access type,因此是ItemType
、Owner
或Value
中的一个,它们已经是您想要的类似键的文字类型的并集。由于Item[K]
已经是keylike的,所以写keyof Item[K]
是对keys-of-keys进行求值。想必你并不关心像"ownerA"
这样的字符串的键(例如,"toUpperCase"
,"length"
等)或像1
这样的数字的键(例如,"toFixed"
)。相反,您应该直接迭代Item[K]
。毕竟,我们想要{[M in Owner]: number}
,nut{[M in keyof Owner]: number}
。在我们做出这个改变之后,
AnotherType
等价于型
如所希望的那样。
Playground链接到代码