我正在尝试根据“键”属性的值更改对象的类型。
我有一些类型,例如AElement
,BElement
,...,ZElement
。每个元素都有一个称为“名称”的通用属性。因此,取决于该属性,必须更改类型。
例如:
// Elements
type AElement = {name:"a"; propA: string;}
type BElement = {name:"b"; propB: number;}
type CElement = {name:"c"; propC: string;}
// ...
type ZElement = {name:"z"; propZ: string; propZZ: number;}
// Map interface
interface ElementsMap {
"a": AElement;
"b": BElement;
"c": CElement;
//...
"z": ZElement
}
// My custom type
type Elem<K extends keyof ElementsMap = keyof ElementsMap> = ElementsMap[K];
// Use it
let elements:Elem[] = [{
name: "a",
propA: "123",
},{
name: "c",
propC: "321",
},{
name: "z",
propZ: "123",
propZZ: 123,
}];
// Test
let test1 = elements[2];
let test2: Elem = {
name: "a",
propA: "123",
}
我希望当我使用Element[]
时,每种类型都取决于键属性“名称”,我可以使用该类型的不同道具。但是test1和test2的变量类型是:每个变量AElement | BElement | CElement | ZElement
,但是我希望ZElement
和AElement
。
答案 0 :(得分:0)
不幸的是,这是“数组”的基础“功能”,并且按预期工作,即使在特定索引下对数组进行索引也将始终产生该数组类型,即使该类型是联合。
无论索引处的值是什么,它都会始终产生Arrays类型,
只能在一个键处索引元组以接收该键处的类型,这是因为它们在运行时具有已知的长度,而Array则没有。
以下面的代码为例。
const testTuple: [AElement, CElement, ZElement] = [{
name: "a",
propA: "123",
},{
name: "c",
propC: "321",
},{
name: "z",
propZ: "123",
propZZ: 123,
}];
const TestTypeAtIndex = testTuple[0] // AElement and not a union.
有很多解决方法,如果您想了解更多,请发表评论,但是我想说,最简单的就是添加一个用户定义的typeguard,更复杂的解决方法可以提供更好的生活质量,复杂的实现。
// use it as array.
const testTuple: Elem[] = [{
name: "a",
propA: "123",
},{
name: "c",
propC: "321",
},{
name: "z",
propZ: "123",
propZZ: 123,
}];
const isAElement = (ele: ElementsMap[keyof ElementsMap]): ele is AElement => {
return "propA" in ele;
}
const testTypeAtIndex = testTuple[0] // union of everything
if(isAElement(testTypeAtIndex)) {
const newTestType = testTypeAtIndex; // inside here its JUST AElement because of typeguard.
}