Rick Kirkham
Rick Kirkham

Reputation: 9659

How to declare a TypeScript interface with variable number of properties?

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

Answers (2)

rickdenhaan
rickdenhaan

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

M1X
M1X

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

Related Questions