映射空对象会导致打字稿错误

时间:2021-07-28 15:03:23

标签: javascript reactjs typescript

我正在映射一个空对象,但它给了我一个错误:

Object is possibly 'undefined'.ts(2532)
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Partial<Point>'.
  No index signature with a parameter of type 'string' was found on type 'Partial<Point>'.

只有当我尝试使用 obj[key] 这样的键访问对象的值时才会发生这种情况,而不是在我显式地使用键上的名称(如 obj.keyname)访问它时发生。

代码:

interface IPoint {
    x: number;
    y: number;
    z: number;
}

interface IScene {
    aspectratio: Partial<IPoint>;
}

interface IObject {
    scene?: Partial<IScene>;
}


const obj: IObject = {
    scene: {
        aspectratio: {
            x: 1,
            y: 2,
            z: 3
        }
    }
}
const { scene } = obj;
{
    scene?.aspectratio
        && (Object.keys(scene.aspectratio) as (keyof typeof scene.aspectratio)[]).map((key) => 
(console.log(scene.aspectratio[key])))//the problem in the console.log
}

如果我将值更改为 scene?.aspectratio?.x 之类的值,它会给我正确的值。

编辑:我添加了一个打字稿游乐场,与我的问题有类似的问题。 https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIAUD2ozIN4BQyxyAHgFzIgCuAtgEbQDcRJAnpTQ868QF6c6jKCwC+BAjmjwkaAMpIQKQiWRwAzgAcICMFDhhgmSujhRDcADYAeDNnAA+MRKmxEKVAHl6AKx24VEnVFCAB+EzMLG1QFCCUnAnEJBEwQdVxMX0ovX39kAF58XmRguIhKQNViDW1dfUNjIqrmskoARgAaYpbkDmQAJi6e1QFkAGZuknFVcXEUtICSkORRAuRMnxZKpbLQgDoa-3qjSeIAMjPkAApvP109gGsINnUr0qUDrSODIwBKNXU1yebEwMGQYDY2lBOw+hzqP0wvwA2gBdX57WhwTRXK7A-75BzXebqTCWCB7SyYADmbxCn1qegRSOBaN+v0SBCAA

2 个答案:

答案 0 :(得分:2)

TypeScript 警告您 scene?.aspectratio 可能是 undefined,这是真的,因为表达式 scene?.aspectratio 的结果是值 undefined if scenenullundefined(当然,如果 aspectratio 是)。

您可能期望自己不会到达那里,因为您在 Object.keys 调用的早期使用了可选链,但可选链只会短路它所属的表达式,而不是它周围的表达式。 Object.keys(scene?.aspectratio) 所做的一切可能只是传递 undefined to Object.keys`(这将引发错误,但 TypeScript 不知道这一点,因此它认为您的其他代码可能会运行)。

我们要确保 TypeScript 知道 scene.aspectratio 不是 undefined。我发现我在缩小 const 变量的类型方面取得了最大的成功,尤其是在有中间函数调用时,因为 TypeScript 无法(实际地)知道函数调用对对象属性的副作用(如sceneaspectratio)。因此,我通常在缩小时将它们抓取到 const,如下所示:

const aspectratio = scene?.aspectratio;
// ...
{
    aspectratio && Object.keys(aspectratio).map((key) => (
        <TextField
            key={key}
            label={key}
            id="outlined-size-small"
            value={aspectratio[key] ?? 0}
            size="small"
        />
    ))
}

但即便如此,您仍有问题,key 可能无法用于索引 aspectratio,因为它是一个字符串,并且大概 aspectratio 不是 Record<string, x> .您可以对 Object.keys 的结果使用类型断言:

const aspectratio = scene?.aspectratio;
// ...
{
    aspectratio && (Object.keys(aspectratio) as (keyof typeof aspectratio)[]).map((key) => (
        <TextField
            key={key}
            label={key}
            id="outlined-size-small"
            value={aspectratio[key] ?? 0}
            size="small"
        />
    ))
}

Updated playground link

答案 1 :(得分:0)

从您的代码示例看来,scene.aspectratio 也可以是 undefined。在这种情况下,scene?.aspectratio[key] 可以索引 undefined。使用更多的可选链接:

scene?.aspectratio?.[key]

这甚至不考虑 Object.key(scene.aspectratio) 也会失败。