我想我基本上了解了TypeScript中索引签名的工作方式。但是,有一件事我不明白。给出以下示例代码:
const sales: {[ key: string ]: number } = {
a: 532,
b: 798,
c: 264
};
console.log(sales.a);
console.log(sales.d);
现在,编译器会说sales.a
和sales.d
的类型为number
。但这不是number | undefined
,因为编译器无法知道a
和/或d
是否确实存在吗?
在这里我无法提出特定的接口,因为a
和d
在运行时是任意选择的,而不是预定义的。
我可以通过使用
解决此问题{[ key: string ]: number | undefined }
作为一种类型,但这似乎既麻烦又烦人(考虑到JavaScript中通常如何使用对象,这对于一个非常琐碎的问题来说是一个相当la脚的解决方案)。
所以,有人可能会说:对我来说,这似乎违反直觉:如果索引签名实际上对地球上所有 个可能的字符串都具有强制意义,那么它具有什么意义呢?究竟是哪种类型?
实际上没有比提出一个更简单的解决方案了
{[ …: string ]: … | undefined }
一遍又一遍地输入?语言中没有任何东西吗?
考虑到存在Partial<T>
和co之类的特产,这很难让人相信。 ……对此有何想法?
PS:Record<T>
(在语义上)与{[ key: string ]: T | undefined }
相同吗?
答案 0 :(得分:5)
它已被raised as a suggestion并已被拒绝(尽管它被列为“等待更多反馈”),因为它预计会导致比其所能解决的错误更多的错误。您是对的,目前的情况是不一致的,并且在技术上不正确/不合理,但是not one of TypeScript's goals是“应用完善的或'证明正确的'类型的系统。相反,[应该]在正确性和生产率之间取得平衡。”
TypeScript实际上并没有强制匹配可能存在的所有可能存在 索引的键(因此索引签名属性实际上是可选的),但是它确实强制了任何这样的键,这些键是 present具有正确类型的定义值...这是TypeScript中missing and undefined are distinguished少数几个地方之一。
如前所述,如果您希望自己的索引签名类型的行为与其他可选属性相同(意味着undefined
自动是一个可能的值),则可以将| undefined
添加到该属性中类型。如果希望现有的索引签名类型以这种方式运行(例如Array
),则必须fork your own copy of the standard library and do it for yourself。他们不会在上游这样做,因为it would make lots of people very sad to deal with this。
如果您真的希望看到这种情况发生变化,则可能需要visit the GitHub issue并进行评论或投票,但我不会屏住呼吸...您的时间可能最好花在克服这个问题上(我从经验...在处理TypeScript的实际不一致时,我不得不做几次。)
我希望能有所帮助。祝你好运!
答案 1 :(得分:2)
这只是已接受答案的补充,因为它是完全正确的
如果您的目的是在不检查例如sales.d
存在/不存在undefined
,您可以在此处实现自己的接口:
interface SomeDictionary<T> {
{[ key: string ]: T | undefined }
}
const sales: SomeDictionary<number> = {
a: 532,
b: 798,
c: 264
};
// compile time error
const result = sales.a + sales.b;
// working
if(sales.a !== undefined && sales.b !== undefined){
const result = sales.a + sales.b;
}
AFAIK在打字稿中没有这样的内置界面。
如果您要遍历此类对象的键,我认为索引签名(对于您而言)很有意义:
const sales: {[ key: string ]: number } = {
a: 532,
b: 798,
c: 264
};
let sum = 0;
for(const key in Object.keys(sales)){
sum = sum + sales[key];
}
我认为目前还没有想到更多用例。
对于您的另一个问题:不,不是(如果您是指here中的Record
。Record<T>
甚至不能编译,因为它需要第二种类型的参数。我会说{ {1}}确实与您的问题无关。