Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create objects dynamically in Typescript

Tags:

typescript

The Javascript code below prints { x: 1 }:

var foo = 'x';
var a = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);

Similarly, I need to dynamically build in Typescript an object, in other words when I create the object i don't know what are going to be its members.

I tried this in Typescript, but it doesn't work:

let foo = 'x';
let a = {};
if (foo == 'x')
    a.x = 1;    //  <-- transpilation fails here
else
    a.y = 2;    //  <-- transpilation fails here 
console.log(a); 

The error is Property 'x' does not exist on type '{}'. Is it possible to create objects dynamically in Typescript?

like image 598
ps0604 Avatar asked Jul 24 '18 16:07

ps0604


People also ask

How do you create a dynamic object?

You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.

How do you dynamically access object property in TypeScript?

To dynamically access an object's property: Use keyof typeof obj as the type of the dynamic key, e.g. type ObjectKey = keyof typeof obj; . Use bracket notation to access the object's property, e.g. obj[myVar] .

How do you create a object in TypeScript?

Syntax. var object_name = { key1: “value1”, //scalar value key2: “value”, key3: function() { //functions }, key4:[“content1”, “content2”] //collection }; As shown above, an object can contain scalar values, functions and structures like arrays and tuples.

How do I add a new property to an object in TypeScript?

To add a property to an object in TypeScript, set the property as optional on the interface you assign to the object using a question mark. You can then add the property at a later point in time without getting a type error. Copied!


2 Answers

TypeScript needs to know about the fields an object will have when you declare the variable. By default the type is inferred based on what you assign to it, since you assign {}, a will be of a type with no properties. You can declare the type for a to something that will suite your needs:

var foo = 'x';
var a : { x?: number; y?:number} = {}; // Both x and y are optional, hence the ?
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);

Using a: any is also a option but you should avoid it as it turns off any checking on a which is probably not what you want since the whole point of typescript is to check as much as possible. I would avoid any unless you don't know both the type of values and the key names.

If you don't know what the keys are at compile time(maybe they are based on user input or a service call) you can also use an index signature that at least will check that the type of the value is valid. For example a type that only allows number values but any key would look like this:

var foo = 'x';
var a : { [n: string]: number} = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);
like image 120
Titian Cernicova-Dragomir Avatar answered Oct 06 '22 04:10

Titian Cernicova-Dragomir


If you do know what all the possible fields can be but you don't know which will be set, you can use a Partial<T>, which obviates the need for you to create a new interface and put :? everywhere, since you might want to inherit from a type / interface whose properties are not all optional:

interface A {
    x: number;
    y: number;
    z: string;
}

let foo = 'x';
let a: Partial<A> = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2; 

If you do not know ahead of time what any of the fields can be, since TypeScript only exists ahead of time (in the compilation phase), another option is to declare it as an any type.

let foo = 'x';
let a: any = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2; 

This is rarely a desirable approach to take, however, because it defeats the purpose of using TypeScript to beign with as it completely disables type-checking.

like image 44
msanford Avatar answered Oct 06 '22 03:10

msanford