我正在构建一个工具来检查网络状态。环境文件有一堆指向各种项目的地址,例如虚拟机、数据库等。环境的类型如下所示:
export type EnvDefinition = {
'DetailedErrors': boolean,
'Logging': LogDefinition,
'SystemElementGroups': {
'VMs': SystemElement[],
'Applications': SystemElement[],
'Databases': SystemElement[],
},
}
SytemElement
只是定义 IP 地址和其他所需内容的另一种类型。
当我从 json 文件加载 env 数据时,我像这样投射它:
import envData from '../development.json';
const data: EnvDefinition = envData;
然后我尝试像这样访问各个组数据:
const assetTypes = ['VMs', 'Applications', 'Databases'];
for (const assetType of assetTypes) {
const connectStrings = data.SystemElementGroups[assetType];
无论我尝试什么,我总是收到 TS 错误:
TS7053: Element implicitly has an any type because expression of type string can't be used to index type
如何定义它以便我可以循环访问
SystemElementGroups
?
谢谢
在排队中
const assetTypes = ['VMs', 'Applications', 'Databases'];
您还没有注释类似
const assertTypes: XXX =
的类型。因此,TypeScript 必须从初始化时使用的 数组文字 推断 assetTypes
的类型。并且它将在 assetTypes
变量的所有后续使用中参考它推断的类型。
有许多可能的类型适用于特定的数组文字。它可以是超级笼统的东西,比如 unknown
类型,也可以非常具体,比如由字符串 文字类型
["VMs", "Applications", "Databases"]
组成的 元组类型。或者介于两者之间的任何东西,例如
Array<string | number> | boolean
。它基于在各种现实代码中运行良好的启发式规则进行选择,但这些规则并不总是符合每个人的要求。对于内部包含字符串文字的数组文字,TypeScript 会将类型推断为
数组:即
Array<string>
或等效的
string[]
。这允许您将新字符串值添加到它上面,或者将它添加到它上面,等等。但这意味着编译器甚至不会尝试跟踪字符串值在数组中或它们所在的位置。同样,这对于许多用例都很有效。
但不幸的是,这意味着 TypeScript 不知道代码
push()
很安全。您正在使用 sort()
类型的 for (const assetType of assetTypes) {
const connectStrings = data.SystemElementGroups[assetType];
data.SystemElementGroups
,它可以是任何字符串,其中大多数不知道是键。这就是错误消息所说的。
问题是
assetType
的类型太笼统,无法满足您的需求。如果您想让编译器相信
string
仅包含
assetTypes
的 assetTypes
可以
注释
SystemElementGroups
:
EnvDefinition
这可行,但有点冗长。
另一种方法是使用a
assertTypes
断言 告诉编译器由数组文字初始化的数组根本不会改变。它将永远是一个由三个元素组成的数组,其类型是初始化元素的字符串文字类型,并且它们将按照初始化时的确切顺序:现在
const
的类型非常具体。你不能在上面const assetTypes = ['VMs', 'Applications', 'Databases'] as const;
// const assetTypes: readonly ["VMs", "Applications", "Databases"]
一些随机字符串,或者assetTypes
它,或者写push()
。这可能比您关心的更具体,但是使用
sort()
很容易做到...现在编译器有足够的信息来知道
assetTypes[0]="random"
的每个元素都是
as const
的有效键:
assetTypes
Playground 代码链接