简体   繁体   中英

Typescript complaining about not assigning a get property

I have this code stackblitz

export class Student {
  id: number;
  name: string;
  age?:number;

  get studentType():string {
    return 'fullTime'
  }

  constructor(params: Student) {
    Object.assign(this, params);
  }
}

const student = new Student({id:1, name: 'Jon'}); //ts error here

I get the below error

Argument of type '{ id: number; name: string; }' is not assignable to parameter of type 'Student'. Property 'studentType' is missing in type '{ id: number; name: string; }'.

While studentType is a get only property and can't bet set.

What is the reason for that and how can I solve it?

ps. (I don't want to make it nullable like studentType? or convert it to just a function)

Getters / Setters are exactly like regular properties, thats why Typescript can't distinguish between a getter / setter and a regular property. You could make all properties optional though, with that you can omit the studentType :

  constructor(params: Partial<Student>) {
     Object.assign(this, params);
  }

However other properties (eg name ) could also be omitted now. To make that more typesafe you could introduce an additional interface:

export interface StudentData {
  id: number;
  name: string;
  age?:number;
}

export class Student implements StudentData {
  get studentType():string {
    return 'fullTime'
  }

  constructor(params: StudentData) {
     Object.assign(this, params);
   }
 }

That is a more controversial topic in TypeScript. For class, TypeScript consider the overall shape of the class to be the type.

This includes private variables and methods, and in this case, including the getter/setter.

One solution to your problem is you can use Partial<>

constructor(params: Partial<Student>) { ... }

or Pick<>

constructor(params: Pick<Student, 'id' | 'name' | 'age'>) { ... }

Another way is to create an interface yourself:

interface IStudent { id: number, name: string, age?:number }
class Student implements IStudent {
  constructor(params: IStudent) { ... }
}

What is the reason for that?

Basically, {id:1, name: 'Jon'} is not a student, since that object lacks a studentType property. This seems obvious and idiotic but makes sense, since typescript cannot know wether you're gonna rely on that property of the argument or not.

In your constructor, you just call Object.assign and let it go. But you could be calling some function that actually relies on the argument having that property, which could led to a runtime error if not pointed out by typescript.

and how can I solve it?

Well, there are several answers already. I would just type the constructor parameter properly. If you expect an object that has id, name and/or age I would type it accordingly:


export class Student {
  id: number;
  name: string;
  age?:number;

  get studentType():string {
    return 'fullTime'
  }

  constructor(params: {id: number, name: string, age?: number}) {
    Object.assign(this, params);
  }
}

const student = new Student({id:1, name: 'Jon'}); //ts error here

This is because you are giving the type in constructor as Student. This can be done:

export class Student {
  id: number;
  name: string;
  age?: number;

constructor(id:number, name:string,age?:number) {
    this.age = age;
    this.name = name;
    this.id = id;
}

  get studentType():string {
    return 'fullTime'
  }

}

const student = new Student(1, 'Jon');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM