线路中
const assetTypes = ['VMs', 'Applications', 'Databases'];
你还没有像const assertTypes: XXX =
这样的annotated个. 因此,TypScript必须将assetTypes
的类型从您初始化时使用的array literal中进行101.它推断的类型将在所有后续使用assetTypes
变量时参考.
有很多可能的类型适用于特定的数组文字. 它可以是超级一般的东西,比如the unknown
type,也可以是非常具体的东西,比如由字符串literal types和["VMs", "Applications", "Databases"]
组成的tuple type. 或者介于两者之间的任何内容,比如Array<string | number> | boolean
. 它基于启发式规则进行 Select ,这些规则在各种现实世界的代码中都很有效,但这些规则并不总是满足每个人的需求.
如果数组文字中包含字符串文字,则TypScript将类型推断为an array(满分string
):即Array<string>
或等效的string[]
. 这允许您在其中添加push()
个新字符串值,或者添加sort()
个字符串值,等等.但这意味着编译器甚至不会try 跟踪数组中的which个字符串值或它们所在的位置. 同样,这对于许多用例都很有效.
但不幸的是,这意味着TypScript不知道代码
for (const assetType of assetTypes) {
const connectStrings = data.SystemElementGroups[assetType];
是安全的您正在用string
类型的assetType
索引到data.SystemElementGroups
,该assetType
根本可以是任何字符串,其中大部分不知道是键.这就是错误消息所说的.
问题是assetTypes
的类型太一般,无法满足您的需求.
如果您想让编译器相信assetTypes
只包含EnvDefinition
的SystemElementGroups
属性的键,请使用could annotate assertTypes
:
const assetTypes: Array<keyof EnvDefinition['SystemElementGroups']> =
['VMs', 'Applications', 'Databases'];
for (const assetType of assetTypes) {
const connectStrings = data.SystemElementGroups[assetType]; // okay
}
这可行,但有点冗长.
另一种方法是使用a const
assertion来告诉编译器由数组字面量初始化的数组根本不会更改.它将永远是一个由三个元素组成的数组,其类型是初始化元素的字符串字面量类型,并且它们将按照初始化时的完全顺序:
const assetTypes = ['VMs', 'Applications', 'Databases'] as const;
// const assetTypes: readonly ["VMs", "Applications", "Databases"]
现在assetTypes
的类型非常具体.你不能在上面添加push()
个随机字符串,或者sort()
个字符串,或者写assetTypes[0]="random"
.这可能比您关心的更具体,但用as const
很容易做到.现在编译器有足够的信息来知道assetTypes
的每个元素都是data.SystemElementGroups
的有效密钥:
for (const assetType of assetTypes) {
const connectStrings = data.SystemElementGroups[assetType]; // okay
}
Playground link to code