【问题标题】:Typescript: Defining an interface with both dynamic and static keysTypescript:使用动态和静态键定义接口
【发布时间】:2021-07-09 13:34:04
【问题描述】:
我正在处理看起来像的数据
{
8533864186048: "4",
8533864218816: "1",
isExchange: true,
returnType: "exchange",
}
前两个键是动态的,但总是字符串
所以我尝试这样定义接口:
interface ReturnData {
[key: string]: string; <- Applying this to whole interface for some reason
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
}
因此,尝试在接口上定义动态成员会导致 ts 尝试分配所有其他成员以键入 string
解决这个问题的正确方法是什么?
【问题讨论】:
标签:
javascript
node.js
typescript
【解决方案1】:
你可以这样做:
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
[key: string]: string | boolean | ReturnType | Variant;
}
但我认为你应该像这样重构你的界面,而不是将动态和静态属性混合在一起:
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
someProps: {
[key: string]: string;
}
}
因此界面更具可读性。
【解决方案2】:
您可以将所有 number 键限制为字符串:[key:number]: string
type CustomReturnType = string;
type Variant = string;
interface ReturnData {
[key: number]: string; // <--- any number key should be a string
isExchange?: boolean;
returnType?: CustomReturnType;
selectedVariant: Variant;
}
const data: ReturnData = {
isExchange: true,
returnType: 'hello',
selectedVariant: 'variant',
2334234234: 'sd',
234234234:23 // expected error
}
【解决方案3】:
你可以这样定义你的界面
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
[key: string]: string | boolean | ReturnType | Variant;
}
如果您只想将编号的键作为字符串,则另一种方法是
type ReturnData = {
[key in string | number]: key extends number ? string : string | boolean | ReturnType | Variant;
} & {
isExchange?: boolean;
returnType?: RT;
selectedVariant: V;
};
const k: ReturnData = {
8533864186048: "4",
8533864186049: "3",
8533864186048: true // invalid
};
最终实现将如下所示
type ValidKeys = "isExchange" | "returnType" | "selectedVariant";
type ReturnData = {
[key in string | number]: key extends ValidKeys ? string | boolean | ReturnType | Variant : string;
} & {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
};