Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 973
Reza Avatar asked Oct 31 '18 19:10

Reza


People also ask

How do you add dynamic properties to object TypeScript?

Use an index signature to dynamically add properties to an object, e.g. const obj: {[key: string]: any} = {} . Index signatures are used when we don't know all of the names of a type's properties and the type of their values ahead of time.

How do you define object of objects type in TypeScript?

To define an object of objects type in TypeScript, we can use index signatures with the type set to the type for the value object. const data: { [name: string]: DataModel } = { //... }; to create a data variable of type { [name: string]: DataModel } where DataModel is an object type.

What is dynamic type in TypeScript?

Dynamically-typed languages are those (like JavaScript) where the interpreter assigns variables a type at runtime based on the variable's value at the time.

How do you assign values to objects in TypeScript?

To use the Object. assign() method in TypeScript, pass a target object as the first parameter to the method and one or more source objects, e.g. const result = Object. assign({}, obj1, obj2) . The method will copy the properties from the source objects to the target object.


1 Answers

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.

like image 127
Willwsharp Avatar answered Sep 25 '22 08:09

Willwsharp