我在使用字符串索引访问对象中的属性时遇到问题,其中接口是使用
in keyof
定义的。
拿这个代码:
interface IFilm {
name: string;
author: string;
}
type IExtra<T extends {}> = {
[index in keyof T]: number;
};
const film : IFilm = { name: "FilmName", author: "AuthorName"};
const extra : IExtra<IFilm> = { name: 1, author: 2};
Object.keys(film).forEach(X => {
extra[x] = 3; // Error here!!
});
我尝试访问的地方
extra[x]
我得到了这个错误:
Element 隐式具有“any”类型,因为类型“any”的表达式不能用于索引类型“IExtra”。
我明白了为什么:typescript 不知道
x
只包含对约束 in keyof T
实际有效的字符串。
因此,我如何重写它,或者让 TypeScript 知道这是有效代码?我知道我可以使用(extra as any)[x]
,但我想接受“类型检查”:)
你的问题是
Object.keys<T>
返回一个 string
,而不是一个 key of T
.
你需要做一个类型断言
extra[x as keyof IFilm] = 3;
如果您想遍历键入的键,请使用
Map
.
Object.keys
不返回keyof T
,因为TS不保证没有其他键:
const notAFilm = { name: '123', author: 'asd', blah: true }
const badFilm: IFilm = notAFilm
const badKeys = Object.keys(badFilm)
console.log(badKeys) // ["name", "author", "blah"]
如果您确定没有其他键,请做一个知道的替代方案:
interface IFilm {
name: string;
author: string;
}
type IExtra<T extends {}> = {
[index in keyof T]: number;
};
const film: IFilm = { name: "FilmName", author: "AuthorName" };
const extra: IExtra<IFilm> = { name: 1, author: 2 };
/** works as expected only if there is no unknown keys */
function recordKeys<T extends {}>(o: T): (keyof T)[] {
return Object.keys(o) as (keyof T)[]
}
recordKeys(film).forEach(x => {
extra[x] = 3; // works fine
});