Im working with data that looks like
{
8533864186048: "4",
8533864218816: "1",
isExchange: true,
returnType: "exchange",
}
where the first two keys are dynamic but will always be strings
so I tried to define the interface as such:
interface ReturnData {
[key: string]: string; <- Applying this to whole interface for some reason
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
}
So am having the issue where trying to define a dynamic member on the interface causes ts to try and assign all the other members to type string
What would be the correct way to go about this?
You could do something like:
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
[key: string]: string | boolean | ReturnType | Variant;
}
But instead of mixing dynamic and static property together, I think you should refactor your interface like this:
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
someProps: {
[key: string]: string;
}
}
so the interface is more readable.
You can just restrict all number keys to be a string: [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
}
You can define your interface like this
interface ReturnData {
isExchange?: boolean;
returnType?: ReturnType;
selectedVariant: Variant;
[key: string]: string | boolean | ReturnType | Variant;
}
Another approach is this if you only want numbered keys to be a string
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
};
Final Implementation will look like this
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;
};