我从后端获取JSON数据(我对此有一些控制权,因此如果有帮助,可以在某种程度上进行更改),如下所示:
{
"attributes": [
{
"type": "string",
"value": "foobar"
},
{
"type": "number",
"value": 1234
},
{
"type": "annotated_string",
"value": {
"value": "barfoo",
"comment": "This is a comment"
}
}
]
}
我想找到一个可以表示此类型的TypeScript类型。我读到有关条件类型的信息,它们似乎与问题的一部分相匹配。
value
取决于type
字段的类型(实际上是其值)。
我想到了这个
type AttributeGroup = {
attributes: Attribute[] // <-- This requires a generic parameter
}
enum AttributeType { "string" , "number", "annotated_string"}
type Attribute<T extends AttributeType> = {
type: T;
value: ExtractMyParameter<T>;
}
type AnnotatedString = {
value: string;
comment: string;
}
type ExtractMyParameter<T> =
T extends AttributeType.number ? number :
T extends AttributeType.string ? string :
T extends AttributeType.annotated_string ? AnnotatedString :
never;
let attr: Attribute<AttributeType.string> = { // <-- Ugly to have to define it twice
type: AttributeType.string, // <-- I don't want to do this but instead: type: "string"
value: "1234"
}
在TypeScript中是否有一种很好的方式将数据表示为类型? 上面的代码由于各种原因而无法正常工作:
Attribute[]
缺少Type参数,但是数组的每个元素都可能具有不同的Type。我想这可以通过Union类型以某种方式解决?我认为必须有更好的方法来处理此类数据。
答案 0 :(得分:1)
值得注意的是,除非您创建这些属性值(您可能会这样做),否则键入不会严格帮助您。否则,您可能会陷入一种虚假的安全感!
您应该能够使用映射类型来实现用例(在这种情况下,这只是编写普通联合的快捷方式:TS Playground
type AttributeType = 'string'|'number'|'custom';
type Attribute<T extends AttributeType|unknown = unknown> = T extends AttributeType ? {
'string': {type: T, value: string};
'number': {type: T, value: number};
'custom': {};
}[T] : {type: unknown, value: unknown};
let attr: Attribute<'string'> = {
type: 'string',
value: "1234",
}
let badValue: Attribute<'number'> = {
type: 'number',
// Type 'string' is not assignable to type 'number'.
value: "1234",
}
let badType: Attribute<'string'> = {
// Type '"number"' is not assignable to type '"string"'.
type: 'number',
value: "1234",
}
我还通过添加默认的unknown
类型来使Attribute []工作。