【发布时间】:2021-05-15 23:19:54
【问题描述】:
注意:TypeScript 使用tsc --strict 调用下面显示的所有代码。
给定一个单例对象o:
const o = {
foo: 1,
bar: 2,
baz: 3,
};
如果我有一个在编译时无法知道的字符串值(比如来自用户输入),我想安全地使用该字符串来索引o。我不想为o 添加索引签名,因为它不是动态的或可扩展的——它总是有这三个键。
如果我尝试简单地使用字符串来索引o:
const input = prompt("Enter the key you'd like to access in `o`");
if (input) {
console.log(o[input]);
}
TypeScript 按预期报告此错误:
error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ foo: number; bar: number; baz: number; }'.
No index signature with a parameter of type 'string' was found on type '{ foo: number; bar: number; baz: number; }'.
console.log(o[input]);
~~~~~~~~
如果我尝试更改条件以在运行时验证 input 的值是 o 的键:
if (input && input in o) {
console.log(o[input]);
}
这不足以让 TypeScript 相信操作是安全的,编译器也会报同样的错误。
但是,如果我在custom type predicate 中封装相同的逻辑来检查input 是否是o 的键,那么程序将按预期编译和工作:
function isKeyOfO(s: string): s is keyof typeof o {
return s in o;
}
if (input && isKeyOfO(input)) {
console.log(o[input]);
}
我的问题是:还有其他方法可以将string 类型的值缩小为keyof typeof o 类型的值吗?我希望有另一种更简洁的方法。我也对使用动态字符串索引对象的用例的通用解决方案感兴趣,这样我就不需要特定于o 的类型谓词。
【问题讨论】: