什么是真正的"常量标签:{ [foo:字符串]:字符串} =",我可以做得更好吗?



我是 TypeScript 的新手。我写了一段如下代码,"它有效"(我用TypeScript 3.7编译我的代码(:

const something: { [foo: string]: string } =  <...> ;

我不想专注于=的右侧。<...>是实际代码的占位符。

我想准确地理解:左手边的结构是什么?我们怎么称呼它?它由哪些部分组成(以及我们如何称呼这些部分(,它实际上提供了哪些保证?

我短暂地认为{ [foo: string]: string }是一个匿名接口声明,但在网上搜索这个术语只会确认我应该更好地了解而不是思考:-(。这让我来到了这里。

我应该说出我的发现。我查找了 TS 规格。我发现{ [foo: string]: string }可能是一个对象类型文字,其中内部部分(TypeBody(似乎是索引签名。索引签名似乎由[ BindingIdentifier : string ] TypeAnnotation组成。我必须说,在阅读了第3.9.4 Index Signatures部分之后,我根本不清楚事情。特别是:BindingIdentifier的作用是什么,foo在我的情况下?我发现显示的代码中的foo可以是任何东西(使用keyxbar而不是foo编译和运行良好(,我发现这令人困惑,这是一种代码气味。我可以在没有foo的情况下逃脱,即没有BindingIdentifier吗?我认为最后一部分与 https://github.com/Microsoft/TypeScript/issues/7803 有关,但这次讨论并没有真正结束,已经有几年了。

其次,这是我的意图:我想用一个内联类型表达式声明变量something,这应该意味着该值必须是完全由string键和string值组成的对象。根据tsc的反馈,我认为我的尝试实现了这一目标。但事实真的如此吗,有没有更清洁的方法来实现这一目标?

它保证某些东西将是带有字符串键和字符串值(同样不能未定义(的 JavaScript 对象(并且不能未定义(。

我个人尽量保持内联文字非常谨慎,所以我通常会将其导出为单独的类型,例如

interface MySomething {
[key: string]: string;
}

此外,由于这是一个如此常见的构造,我创建了我唯一的全局类型,以便能够在任何地方本机使用它。这是一种Dict类型,如下所示:

// src/global.d.ts
declare interface Dict<T = any> {
[key: string]: T;
}

这意味着在这种情况下,我可以简单地拥有...

const something: Dict<string> = <...>;

解决您的另一个观点,密钥的名称确实是任意的,但我发现根据它所代表的内容给它一个合理的名称是有帮助的,作为任何使用该类型的人的代码即文档的形式。

最新更新