4

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?

1

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Welcome to StackOverflow! Please edit your answer to explain what this code does and how it answers the question, so that it is useful to people with similar issues. See: How do I write a good answer?
I'm really surprised TypeScript doesn't support this.
1

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
}

Comments

0

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;
};

2 Comments

Is there no way to limit additional keys to just being of string type?
try the latest updated version. It should work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.