typescript 访问对象属性:元素隐式具有“any”类型

typescript access object property: Element implicitly has an 'any' type

提问人:json 提问时间:4/3/2023 最后编辑:json 更新时间:4/3/2023 访问量:300

问:

我正在处理一个代码库,我需要从属性中访问一个值。step

interface Car {
    name: string;
    age: number;
    color: string;
    step: {
        something: {
            onea: string;
            oneb: string;
        },
        anotherone: {
            twoa: string;
            twob: string;
        }
    }
};

const car: Car = {
    name: 'Some name',
    age: 200,
    color: 'something',
    step: {
        something: {
            onea: 'one a value',
            oneb: 'one b value'
        },
        anotherone: {
            twoa: 'two a value',
            twob: 'two b value',
        }
    }
};

const color = car.color;
const firstStep = car.step[color];

color将始终是属性中的一个条目,在我的示例中将返回错误。step

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ something: { onea: string; oneb: string; }; anotherone: { twoa: string; twob: string; }; }'.
  No index signature with a parameter of type 'string' was found on type '{ something: { onea: string; oneb: string; }; anotherone: { twoa: string; twob: string; }; }'.

我尝试的是尝试在尝试获取值时使用关键字,但同样没有变化。typeof

const firstStep = car.step[typeof color]
TypeScript 对象 属性

评论

0赞 Ramesh Reddy 4/3/2023
将永远是其中的关键之一?colorstep
1赞 json 4/3/2023
道歉。我更改了问题,因此它包含所有必要的信息。@RameshReddy,是的,这将是 .step
0赞 jcalz 4/3/2023
这种方法是否满足您的需求?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么?
0赞 json 4/3/2023
@jcalz是的,这就是我所追求的。所以我缺少的一点是.最好有一篇基本的文章来解释这是在做什么。谢谢。as const satisfies Car
0赞 jcalz 4/3/2023
好吧,当我有机会时,我会这样做。

答:

1赞 jcalz 4/3/2023 #1

如果你像这样注释car

const car: Car = {
    ⋯✂⋯
    color: 'something',
    ⋯✂⋯
};

那么你基本上就丢弃了初始值设定项中任何更具体的信息。编译器只会知道这是一个 .这将允许您进行任何更改以与 的定义一致,例如carCarcarCar

car.color = "purple";

编译器甚至不会尝试跟踪任何实际值。只是:car.colorstring

const color = car.color;
//const color: string

因此,您将无法索引 with ,因为编译器只允许您使用已知键进行索引。car.stepcolor"something" | "anotherone"

const firstStep = car.step[color]; // error!

因此,如果要从其初始化值中跟踪特定详细信息,则无法对其进行注释。此外,如果只是为其分配一个对象文本,编译器将不会意识到您希望它注意属性的文本类型。同样,它只会推断 ,因此您可以更改它:carcolorstring

const car = {
    ⋯✂⋯
    color: 'something',
    ⋯✂⋯
};
car.color = "purple";
const color = car.color;
//const color: string
const firstStep = car.step[color]; // error!

哎呀。


您必须走得更远,并要求编译器将初始值设定项值视为尽可能不可变或常量。为此,您可以对该初始值设定项值使用 const 断言

const car = {
    ⋯✂⋯
    color: 'something',
    ⋯✂⋯
} as const;

现在,编译器将被视为一个只读属性,其类型是字符串文本。现在,终于,这足以让你的其余代码工作:color"something"

const color = car.color;
// const color: "something"
const firstStep = car.step[color]; // okay

这很好,除了我们实际上根本没有使用,这意味着编译器不会发现这样的错误Car

const car = {
    ⋯✂⋯
    age: "quite old",
    color: 'something',
    ⋯✂⋯
} as const; // no error

其中 是 a 而不是 .为了在不注释的情况下恢复类型检查,我们可以使用 satisfies 运算符agestringnumber

const car = {
    ⋯✂⋯
    age: "quite old",
    color: 'something',
    ⋯✂⋯
} as const satisfies Car; // error!
// ----------------> ~~~
// Types of property 'age' are incompatible.

错误已被捕获,我们可以更正它:

const car = {
    ⋯✂⋯
    age: 200,
    color: 'something',
    ⋯✂⋯
} as const satisfies Car; // okay

所以现在你拥有两全其美的优势!

Playground 代码链接