Access `in keyof T` using a string [重复]

问题描述 投票:0回答:2

我在使用字符串索引访问对象中的属性时遇到问题,其中接口是使用

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]
,但我想接受“类型检查”:)

javascript typescript
2个回答
0
投票

你的问题是

Object.keys<T>
返回一个
string
,而不是一个
key of T
.

你需要做一个类型断言

extra[x as keyof IFilm] = 3;

如果您想遍历键入的键,请使用

Map
.


0
投票

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
});
© www.soinside.com 2019 - 2024. All rights reserved.