打字稿可选 属性 带有 getter

typescript optional property with a getter

这是一个简化的例子:

class PersonParms{
    name:string;
    lastName:string;
    age?:number;
    get fullName(){return this.name + " " + this.lastName;}
}

class Person{
    constructor(prms:PersonParms){
    }
}

new Person({name:'John',lastName:'Doe'})  // ts error: Property 'fullName' is missing in type '{ name: string; lastName: string; }'.

想法是将文字对象作为 PersonParms 的 intizalizer 传递,但是有了 getter,您既不能声明 getter 可选,也不能将 属性 添加到对象文字。还有其他方法可以实现吗?

Is there another way to achieve it?

以下是我的做法:

class Person {
  constructor(public config: { name: string, lastName: string }) {}
  age?: number;
  get fullName() { return this.config.name + " " + this.config.lastName; }
}

new Person({ name: 'John', lastName: 'Doe' }) 

非常有趣。我认为,你应该 report an issue 到 TypeScript,因为方法可以是可选的(见下文),但 属性 吸气剂不是。这很奇怪.. 作为一种解决方法,我可以建议两种变体。一个不错的:

class PersonParms {
    name:string;
    lastName:string;
    age?: number;

    getFullName?() {return this.name + " "+this.lastName;}
}

还有第二个,这是 hacky,因为我们在传递给构造函数时将所有属性设为可选。

class PersonParms {
    name:string;
    lastName:string;
    age?: number;

    get fullName(){return this.name + " "+this.lastName;}
}

class Person{
    constructor(prms: Partial<PersonParms>){
    }
}

我找到了适合我的解决方案:

class Person {
  name?:string;
  lastName?:string;
  age?: number;
  fullName?:string;

  constructor(public config: { name: string, lastName: string }) {
    Object.defineProperty(this,'fullName',{
           get(){return this.name + " " + this.lastName;}
          });

}
class PersonParms {
  name: string;
  lastName: string;
  age?: number;
  fullName?: string = this.name + ' ' + this.lastName;
}

class Person {
  constructor(prms: PersonParms) {
  }
}

new Person({ name: 'John', lastName: 'Doe' });
   class PersonParms {
      name: string;
      lastName: string;
      age?: number;

     getFullName?(): string | null { return this.name + ' ' + this.lastName; }
  }

  class Person {
     constructor(prms: PersonParms) {
     }
  }
 new Person({ name: 'John', lastName: 'Doe' });

如果您创建一个新的 PersonParms 实例,那么错误将消失。

class PersonParms{
    name:string;
    lastName:string;
    age?:number;
    get fullName(){return this.name + " "+this.lastName;}
}

class Person{
    constructor(prms:PersonParms){
    }
}

const personParams = new PersonParms();
personParams.name = 'John';
personParams.lastName = 'John';
new Person(personParams)  // No error because this is an instance of PersonParams

我不确定 where/how 你是否使用 PersonParms.fullname 但在你的情况下我会使用这个:

interface PersonParms{
    name:string;
    lastName:string;
    age?:number;    
}

class Person implements PersonParms{
    name: string;
    lastName: string;
    age?:number
    constructor(prms: PersonParms) {
        this.name = prms.name;
        this.lastName = prms.lastName;
        this.age = prms.age;
    }

    get fullName(){return this.name + " "+this.lastName;}
}

const person = new Person({ name: 'John', lastName: 'Doe' });

console.log(person.fullName); // John Doe

截至 2020 年 4 月,没有 方法来实现这一点。

对此有一个不确定的 PR: https://github.com/microsoft/TypeScript/pull/16344

此处介绍了通过界面提出的解决方案: https://github.com/microsoft/TypeScript/pull/16344

就我个人而言,该解决方案不符合我的需求,我宁愿将 属性 声明为私有。

希望我们以后能有更好的运气。

如果转换对象,这将防止编译时错误。

export class IndividualModel {
    constructor(individual: IndividualModel = null) {
        if (individual) {
            this.individualKey = individual.individualKey;
            this.firstName = individual.firstName;
            this.lastName = individual.lastName;
        }
    }

    individualKey: string;
    firstName?: string;
    lastName?: string;
    get fullName(): string {
        return `${this.lastName}, ${this.firstName}`;
    }
}
const individual = new IndividualModel(<IndividualModel>{ individualKey: 'some-key' });

请记住,可选是一个类型概念。 getter 是一个实现。实现可以 return 可选类型。在实现带有可选只读 属性 接口的 class 中,class 可能会离开 getter。查看此答案 get and set in TypeScript