Reputation: 9659
This is a simple question, and I'm surprised that I can't find a clear answer to it anywhere. I'm making an API and I need to define an Interface that can have multiple (string) properties, but there's no set number of properties and no set names for them (but they all have to have string values). So all of the following objects would match the type:
{ slot: "ten" }
{ class: "Luxury", base: "never", city: "Timbuktu" }
{ slot: "ten", class: "Luxury" }
I've thought of the following.
interface MyInterface {
[key: string]: string;
}
But to me, this says that the objects can have only one property (of varying name), rather than that they can have multiple properties (of varying names).
What's the best way to do this? Note that I can't control what property names the code that calls my API will use. Callers can use whatever property names that they want.
Upvotes: 18
Views: 13279
Reputation: 11298
Your interface
might look like it only accepts a single property that has to be of type string
, but that is actually the syntax used to define an interface with any number of properties that all share the same characteristics (strings as keys and strings as values). This is called an indexable type (credits to @axiac, I didn't know it had a name).
So there's nothing wrong with keeping the interface as it is:
interface MyInterface {
[key: string]: string;
}
Typescript comes with a native utility type called Record that boils down to the same thing but is more concise:
type MyInterface = Record<string, string>;
Functionally there's no difference between the two, which one you choose is up to your personal preference.
Upvotes: 31
Reputation: 5354
You can’t and you should not do that. That’s the whole point of interfaces, to have a set of defined types. what you can do is: define all property names that you are expecting and mark them as optionals or refactor your models. Try avoiding [key: string]: string; it will compile now but will give you a headache later trying to fix those bugs.
Upvotes: -4