9

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?

2 Answers 2

9

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);
Sign up to request clarification or add additional context in comments.

3 Comments

Indeed, index signature is a much nicer approach.
@msanford lots of choices really. You can model a lot of stuff in the type system, the problem is that you need to know all the options to pick the best one. can be a bit overwhelming especially when starting out
And that is the only reason I'm not deleting my answer: it might help someone. :)
5

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.