[英]Access optional keys in object, where key is a literal in a literal union type without error "Object is possibly 'undefined'"
Let's say I have a type Fields假设我有一个字段类型
export type NodeId =
| "a-index"
| "b-index"
| "c-index"
export type Fields = {
[id in NodeId]?: {
[sectionId: string]: {
[name: string]: string;
};
}
};
Why does the first set error with Object is possibly 'undefined'
, but not the second set?为什么
Object is possibly 'undefined'
的第一组错误Object is possibly 'undefined'
,而第二组则不是?
const test: Fields = {};
const id = "a-index";
// Why does this error
let resultA;
if (test[id]) {
resultA = test[id]["somesection"]
^^^^^^^^
error TS2532: Object is possibly 'undefined'.
}
// But this works fine?
let resultB;
if (test["a-index"]) {
resultB = test["a-index"]["somesection"]
}
The only difference being that I assigned id
to a variable.唯一的区别是我将
id
分配给了一个变量。 Even explicitly typing id
as NodeId
doesn't satisfy typescript.即使将
id
明确键入为NodeId
也不满足打字稿。
This is a known issue, microsoft/TypeScript#10530 .这是一个已知问题, microsoft/TypeScript#10530 。 The problem is that the compiler only spends time narrowing the type of an object property if the property access is direct , either by using a dotted identifier or by using bracket index with a string literal.
问题是,如果属性访问是直接的,编译器只会花时间缩小对象属性的类型,无论是通过使用带点标识符还是使用带有字符串文字的括号索引。 So your
resultB
version works:所以你的
resultB
版本有效:
let resultB;
if (test["a-index"]) {
resultB = test["a-index"]["somesection"]
}
But the resultA
version doesn't because id
, even though it is a const
whose type is the literal "a-index"
, is a variable and the compiler doesn't do narrowing for it.但是
resultA
版本不是因为id
,即使它是一个类型为文字"a-index"
的const
,也是一个变量,并且编译器不会对其进行缩小。 According to microsoft/TypeScript#10565 , an initial attempt to address this, adding this functionality significantly worsens the compiler perfomance.根据microsoft/TypeScript#10565 ,最初尝试解决此问题,添加此功能会显着降低编译器性能。 I guess having to check every possible indexing-into-an-object is more expensive than the potential control flow narrowing saves you.
我想必须检查每个可能的对象索引比潜在的控制流缩小为您节省的成本更高。
The workaround here, in the case where you can't just replace id
with a string literal, is to do the property access once and save its result to a new variable.如果不能仅用字符串文字替换
id
,这里的解决方法是执行一次属性访问并将其结果保存到新变量中。 Then type guards should work on this variable as expected:然后类型保护应该按预期在这个变量上工作:
let resultA;
const testId = test[id];
if (testId) {
resultA = testId["somesection"]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.