英文:
How to create a guard in Typescript for keys in a nested object?
问题
以下是代码的中文翻译部分:
type PossibleKeys = 'a' | 'b' | 'c';
type MappedObject = {
test: {
[key in PossibleKeys]?: { foo: boolean };
}
}
const mappedObject: MappedObject = {
test: {
a: { foo: true },
b: { foo: false },
}
}
function mappedObjectHasKeyDefined(possibleKey: PossibleKeys): possibleKey is keyof MappedObject['test'] {
return possibleKey in mappedObject.test;
}
const c: PossibleKeys = 'c';
const array: PossibleKeys[] = ['a', 'b', 'c'];
array.forEach((newT: PossibleKeys) => {
// 所有这些类型保护似乎都不起作用
if(
mappedObject.test[newT] !== undefined
&& newT in mappedObject.test
&& mappedObject.test
&& mappedObject.test[newT]
&& Object.prototype.hasOwnProperty.call(mappedObject.test, newT)
&& mappedObjectHasKeyDefined(newT)
) {
// 对象可能为 'undefined'。
const a = mappedObject.test[newT].foo;
}
})
英文:
I have a nested object that contains an object with multiple optional properties. I would like to create a typeguard to prevent the Object is possibly undefined
. I do not know if this is possible or that I should cast it.
type PossibleKeys = 'a' | 'b' | 'c';
type MappedObject = {
test: {
[key in PossibleKeys]?: { foo: boolean };
}
}
const mappedObject: MappedObject = {
test: {
a: { foo: true },
b: { foo: false },
}
}
function mappedObjectHasKeyDefined(possibleKey: PossibleKeys): possibleKey is keyof MappedObject['test'] {
return possibleKey in mappedObject.test;
}
const c: PossibleKeys = 'c';
const array: PossibleKeys[] = ['a', 'b', 'c'];
array.forEach((newT: PossibleKeys) => {
// all of these guards somehow do not seem to work
if(
mappedObject.test[newT] !== undefined
&& newT in mappedObject.test
&& mappedObject.test
&& mappedObject.test[newT]
&& Object.prototype.hasOwnProperty.call(mappedObject.test, newT)
&& mappedObjectHasKeyDefined(newT)
) {
// Object is possibly 'undefined'.
const a = mappedObject.test[newT].foo;
}
})
答案1
得分: 0
TypeScript当前不会在obj[key]
形式的属性访问的外观类型上进行缩小,当key
不是单一字符串字面类型时。如果key
只是string
类型,或者如果它是字符串字面类型的联合类型(如PossibleKeys
),或者如果它是泛型类型,编译器将不会缩小属性的类型。这仍然是一个待解决的功能请求,跟踪在microsoft/TypeScript#10530。
目前的解决方法是将属性复制到一个新变量中,因为变量可以通过检查来缩小类型。以下是一种方法:
array.forEach((newT: PossibleKeys) => {
const t = mappedObject.test; // 可行
const u = t[newT]; // 可行
if (u) {
const a = u.foo // 可行
}
})
英文:
TypeScript doesn't currently narrow the apparent types of property accesses of the form obj[key]
when key
is not of a single string literal type. If key
is just of type string
, or if it's a union of string literal types (like PossibleKeys
) or if it's a generic type, the compiler will not narrow the type of the property. This is still an open feature request, tracked at microsoft/TypeScript#10530.
Currently the workaround is to copy the property into a new variable, since variables can be narrowed via checks. Here's one way to do it:
array.forEach((newT: PossibleKeys) => {
const t = mappedObject.test; // okay
const u = t[newT]; // okay
if (u) {
const a = u.foo // okay
}
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论