Aragorn
Aragorn

Reputation: 5289

How to initialize an object in TypeScript

I have a simple model class

export interface Category {

  name: string;
  description: string;

}

I need to declare and initialize a variable in an angular component. Tried:

category: Category = {};

Error: {} is not assignable to a Category

category: Category = new Category();

error: Category refers to a type, but being referred as value..

Any suggestions?

Upvotes: 135

Views: 307709

Answers (12)

MDT
MDT

Reputation: 1695

Other ways to initialize an object would be by using pipe (|) to define multiple types which is best if you expect the object to be filled out in the future say by a callback or rest call.

But you may have to handle the cases of nullability here else you will end up with null ref exception.

Here is a sample usage:

export class MyClass{
    myObject : MyObject | null = null;
}

Note : myObject field is expected by compiler to be initialized by values or null

Another way is to use the undefined fields, this way the compiler won't expect an initializer

export class MyClass{
    rates : MyObject | undefined; //compiler doesn't expect it to be initalized
}

Upvotes: 0

Dave Lee
Dave Lee

Reputation: 524

let category = <Category>{ };

This is the way when you don't want to change the definition of either interface or class.

In this way will be generic type of object which isn't dependent on the data type and is also reusable.

Upvotes: 1

user1187282
user1187282

Reputation: 1237

You can do :

interface Person{
    id: number; 
    name: string;
}

person : Person = new Person;

Upvotes: -5

moto
moto

Reputation: 940

export interface Category {
  name: string;
  description: string;
}


category = {} as Category ;

Edit: Wanted to put the comment below in the answer so people know why my answer is wrong. I was assuming you would always assign right after, but that's not a good assumption to make.

now you have an object in your system that is assumed to be of some type, but with some required properties missing. this is just bad advice causing errors somewhere down the line.

Upvotes: 26

Nikolaev
Nikolaev

Reputation: 1

You can use Record type as well.

{
    category: Record<string, string>;
}

Upvotes: 0

Vitor M. Barbosa
Vitor M. Barbosa

Reputation: 3646

If you don't want to change your definition from interface to class, you could also do:

let category = <Category>{ };

Otherwise, you could follow other answers and change your Category to be a class.

edit: as per ruffin's comment below, if the interface is

export interface ITiered { one: { two: { three: function (x) {...} } } } 

and you try let x = {} as ITiered, then you'll have an error when you call something like x.one.two.three()

Upvotes: 59

Subhashis Pal
Subhashis Pal

Reputation: 149

If you already have a class and you want to create new instance and initialize properties at the same time you can try this

return Object.assign(new Person(), {
    name:"Your Name"
});

Upvotes: 3

Ian MacDonald
Ian MacDonald

Reputation: 14030

There are a number of ways to solve this problem, depending on your desired result.

Way 1: Convert your interface to a class

export class Category {
  name: string;
  description: string;
}
const category: Category = new Category();

Way 2: Extend your interface as a class

export class CategoryObject implements Category {
}
const category: Category = new CategoryObject();

Way 3: Fully specify your object, matching the interface

const category: Category = {
  name: 'My Category',
  description: 'My Description',
};

Way 4: Make the properties optional

export interface Category {
  name?: string;
  description?: string;
}

const category: Category = {};

Way 5: Change your variable's type to use Partial<T>

export interface Category {
  name: string;
  description: string;
}

const category: Partial<Category> = {};

Upvotes: 235

spec
spec

Reputation: 449

Like C# class:

export class Category {
    category: number = null;
    description: string = null;
    name: string = null;

  public constructor(init?: Partial<Category>) {
        Object.assign(this, init);
}
}

Now when you create a new instance all field names are disponible and empty.

 const instance_of_category: Category = new Category();

now you have emty class object with all fields defined like c#:

instance_of_category{
    "category": null,
    "description": null,
    "name": null
}

Upvotes: 7

nightingale2k1
nightingale2k1

Reputation: 10335

interface Person{
    id: number; 
    name: string;
}

let x: Person = {
    id : 0,
    name :"JOHN"
};

alert(x.name);

Upvotes: 1

Jake Holzinger
Jake Holzinger

Reputation: 6063

Your object literal must match the interface. Since your interface has two required properties (name and description) they must both be declared when the object is instantiated.

const category: Category = {
    name: 'foo',
    description: 'bar'
};

If you cannot construct the entire object up front you can use the builtin Partial type to build the object.

const builder: Partial<Category> = {};
builder.name = 'foo';
builder.description = 'bar';

const category: Category = builder as Category;

Upvotes: 6

Serdar
Serdar

Reputation: 797

In Typescript if you want to use Object Initializer you need to define all properties in the class.

let category: Category = {
    name: '',
    description: ''
};

With this way your model still can be remain as an interface.

Upvotes: 25

Related Questions