Warm tip: This article is reproduced from stackoverflow.com, please click
typescript typescript2.0

How to fill properties of class TypeScript?

发布于 2020-03-31 22:57:18

Lets assume there is a model class like:

class Filter implements IFilterJournal {
  public category: number;
  public subject: number;
  public teacher: number;
  public mark: number;
}

I can create instance of this class:

let f = new Filter();

It returns object Filter with empty properties inside.

How to fill properties of class more convenient?

I can determine consturctor like:

public constructor(public category: number, public subject: number, public teacher: number, public mark: number){
}

Then at the time of creation instance pass parameters:

let f = new Filter(1, 2, 3, 4)

But what if I need to fill only public subject: number; property? either others? How to fill them selectively?

Another was is to make parameters as optional:

public constructor(public category?: number, public subject?: number, public teacher?: number, public mark?: number){}

Then use this like:

let f = new Filter(subject = 1);
Questioner
OPV
Viewed
17
Titian Cernicova-Dragomir 2018-05-29 20:24

If you can initialize the object with any combination of properties, you can use a constructor that takes Partial<Filter> as an argument, and uses Object.assign to set the fields on the object.

class Filter  {
    constructor(data: Partial<Filter>){
        Object.assign(this, data);
    }
    public category: number;
    public subject: number;
    public teacher: number;
    public mark: number;
}
new Filter({ category: 0})
new Filter({ category: 1, subject: 2, teacher: 3, mark: 4})

Note Partial is a mapped type that keeps the members of a type but marks all of them as Partial. See docs. In this case Partial<Filter> is equivalent to:

interface PartialFilter{
    category?: number;
    subject?: number;
    teacher?: number;
    mark?: number;
}

If your type has methods, Partial would allow the argument to the constructor to contain those methods, this may be an issue. You can use conditional types to filter out methods from the argument, but it's a bit more complicated:

type NotFunctions<T> = { [P in keyof T]: T[P]  extends Function ? never : P }[keyof T];
class Filter  {
    constructor(data: Partial<Pick<Filter, NotFunctions<Filter>>>){
        Object.assign(this, data);
    }
    public category: number;
    public subject: number;
    public teacher: number;
    public mark: number;

    public sayHi(){ return "Hi" }
}
new Filter({ category: 0, sayHi: ()=> {}}) //Error with new constructor argument type 
new Filter({ category: 0})
new Filter({ category: 1, subject: 2, teacher: 3, mark: 4})