Reza
Reza

Reputation: 19843

How to define type for object with dynamic properties in TypeScript

I have an object which has title as string and order as number, and then there will be dynamic number of properties of type number on it

So I tried to define it like below

appraisalGroups: Array<{
    title: string,
    order: number,
    [key:string]: number,
}>;

and later this will be assigned like this (this is just an example in my read application there will be a loop and keys are coming from a rest api)

this.appraisalGroups[0]['mykey1'] = 5

and I got ts error

Property 'title' of type 'string' is not assignable to string index type 'number'

My question is how can I make it typed?

https://stackblitz.com/edit/angular-mzdwmn

Upvotes: 9

Views: 9700

Answers (1)

Willwsharp
Willwsharp

Reputation: 723

You are getting this because index signatures force all properties to match their return type. As stated in Typescript docs: https://www.typescriptlang.org/docs/handbook/interfaces.html

While string index signatures are a powerful way to describe the dictionary pattern, they also enforce that all properties match their return type.

An index signature is explicitly saying "whenever this object is indexed with a value of this type, it will return a value of that type".

In your example, your index signature says that "whenever this object is indexed with a string, it will return a number". However, the compiler sees that this rule can be broken because one of your properties is not a number, so it throws an error.

I'm not sure what your problem space is but if the dynamic properties all have something in common, then it might be easier to create an interface to abstract their commonalities away. How you use said interface really depends on what you want to do though.

EDIT: You could also be cheeky and take a shortcut and simply use a Union type. So instead of [key:string]: number you do [key:string]: number | string.

Upvotes: 5

Related Questions