使用字符串访问接口/类属性的正确方法是什么?
我有以下界面
interface Type {
nestedProperty: {
a: number
b: number
}
}
我想使用这样的数组迭代来设置嵌套属性:
let myType:Type = ...
["a", "b"].forEach(attributeName => myType.nestedProperty[attributeName] = 123)
TS抱怨“ nestedProperty”没有字符串索引类型。如果我加上typeguard(例如if (attributeName === "a"))
编译器是否满意,但我真的不想走if (...===... || ...===... || ... ) {
路线。
我也不想使用索引类型:
interface Type<T> {
[index:string]: <T>
a: <T>
b: <T>
}
由于不是动态结构,因此属性和属性可以具有不同的类型。
我敢肯定有一些优雅的方法可以做到,但是似乎在文档/ Stack Overflow / web的任何地方都找不到。
我应该为此编写自定义后卫返回联合类型谓词吗? 像这样吗?
(attribute: string): attribute is ('a' | 'b') { ... }
答案 0 :(得分:1)
您必须明确告诉TypeScript您正在使用的数组仅包含nestedProperty
属性中用作键的属性。
interface Type {
nestedProperty: {
a: number
b: number
}
}
// Create a type alias for convenience. The type itself
// is a list of keys allowed in the `nestedProperty`.
type NestedAccessors = Array<keyof Type['nestedProperty']>
// Now TS is happy to do anything with the list since it
// can guarantee you're using proper values.
(["a", "b"] as NestedAccessors).forEach(attributeName => myType.nestedProperty[attributeName] = 123)
答案 1 :(得分:0)
我会选择:
interface Type {
nestedProperty: {[key in ('a' | 'b')]: number}
}
let myType:Type = {
nestedProperty: {
a: 1,
b: 2,
}
};
(["a", "b"] as Array<'a'|'b'>).forEach(attributeName => myType.nestedProperty[attributeName] = 123)
鉴于此问题,如果您不想声明其他类型,则可以采用这种方法。但是我喜欢更明确声明的内容,例如接受的答案。