大家好!😊
interface Thing {
name: string;
}
interface ThingMap {
[thingName: string]: Thing;
}
interface ThingMapClassA {
first: { name: 'first thing name' };
second: { name: 'second thing name' };
third: { name: 'third thing name' };
}
interface ThingMapClassB {
first: { name: 'first thing name' };
second: { name: 'second thing name' };
third: { name: 'third thing name' };
}
class Handler<T extends ThingMap> {}
const handler = new Handler<ThingMapClassA>();
我喜欢Handler
接受任何具有Thing
类型属性(理想情况下至少一个)的类。但是ThingMapClassA
不被识别。这会导致错误。有什么建议吗?😊
1条答案
按热度按时间qxgroojn1#
类型
具有字符串索引签名,这意味着如果该类型的对象具有键为
string
的属性,则该属性的值将为Thing
。如果你有一个匿名对象类型,比如从对象字面量推断的类型,并试图将其分配给一个具有索引签名的类型,编译器将帮助它提供一个隐式索引签名:
但是隐式索引签名 * 不 * 给予接口或class示例类型的值。这在microsoft/TypeScript#15300中描述。观察:
这就是你遇到的问题。
ThingMapClassA
和ThingMapClassB
不能赋值给ThingMap
,即使一个与之等价的匿名对象文字类型可以赋值给ThingMap
。所以你需要改变你正在做的事情。这里最简单的方法是将约束改为递归的。你只想知道它的属性可以赋值给
Thing
。这可以表示为使用
Record<K, V>
实用程序类型。Record<keyof T, Thing>
表示“与T
具有相同键的对象,其属性的类型为Thing
”。因此,如果T extends Record<keyof T, Thing>
,则我们知道T
的每个属性的类型为String
。这就给了我们
和
如所期望的。
Playground代码链接