我正在处理一个代码库,我需要从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]
1条答案
按热度按时间cngwdvgl1#
如果像这样注解
car
那么你实际上是丢弃了初始化器中的任何更具体的信息。编译器只会知道
car
是Car
。这将允许你对car
进行任何与Car
的定义一致的更改,如编译器甚至不会试图跟踪
car.color
的实际值,它只是string
:所以你不能用
color
索引car.step
,因为编译器只允许你用已知的键"something" | "anotherone"
索引。因此,如果你想让
car
从它的初始化值中跟踪特定的细节,那么你不能注解它。此外,如果你只是给它分配一个对象文字,编译器不会意识到你想让它注意color
属性的文字类型。同样,它只会推断string
,因此你可以改变它:哎呀。
你必须更进一步,要求编译器尽可能地将初始化器的值视为不可变或常量。你可以通过对该初始化器值使用
const
Assert来做到这一点:现在,编译器将把
color
当作readonly
属性,其类型是字符串文字"something"
。现在,最后,这足以让剩下的代码工作:这很好,只是我们实际上根本没有使用
Car
,这意味着编译器不会捕获这样的错误其中
age
是一个string
而不是一个number
。为了恢复不带注解的类型检查,我们可以使用satisfies
操作符:错误已被捕获,我们可以更正它:
所以现在你拥有了两个世界的最佳选择!
Playground链接到代码