【问题标题】:typescript optional property with a getter带有 getter 的 typescript 可选属性
【发布时间】:2018-07-21 09:49:39
【问题描述】:

这是一个简化的例子:

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 声明为可选,也不能将属性添加到对象文字中。还有其他方法可以实现吗?

【问题讨论】:

  • 考虑定义一个接口interface IPersonParms { name:string; lastName:string; age?:number; readonly fullName?: string; }。将对象文字转换为类似乎没有用 - 无论如何,getter 不会神奇地出现在那里,您需要创建一个 PersonParms 类的实例。

标签: typescript optional getter object-literal


【解决方案1】:

非常有趣。我认为,你应该 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>){
    }
}

【讨论】:

  • 我同意这一点。必须为初始化中(故意)只读的属性分配一个值是非常误导性的 - 这实际上是此处描述的案例需要我们的地方。
【解决方案2】:

截至 2020 年 4 月,没有没有方法可以实施。

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

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

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

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

【讨论】:

  • 您的评论为我节省了数小时寻找不存在的解决方案的时间。我觉得这不可能是疏忽,一定是我不理解一些打字稿语法。但是不……这个重要的、基本的东西确实没有实现,现在打字稿正在阻止我做应该做的事情。惊人的。设置为私有不是一种解决方法,我还没有找到。
【解决方案3】:

还有其他方法可以实现吗?

我会这样做:

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' }) 

【讨论】:

  • 是的,但我将在其他几个类中使用 PersonParms 作为基础,因此可选的 getter 应该在 PersonParns 中,而不必在所有子类中重复它。
【解决方案4】:

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

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;}
          });

}

【讨论】:

    【解决方案5】:

    如果你创建一个新的 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
    

    我不确定你在哪里/如何使用 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
    

    【讨论】:

      【解决方案6】:

      记住 optional 是一个类型概念。 getter 是一种实现。实现可以返回一个可选类型。在实现具有可选只读属性的接口的类中,该类可以不使用 getter。看到这个答案get and set in TypeScript

      【讨论】:

        【解决方案7】:
        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' });
        

        【讨论】:

        • 嗨,Akshay,您不仅应该显示代码,还应该说明您所做的更改以及解决问题的原因。
        • 这里我只做了一处改动。 fullName?: string = this.name + ' ' + this.lastName;
        • 在构造函数中设置。不是 getter setter 的替代品
        【解决方案8】:

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

        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' });
        

        【讨论】:

          【解决方案9】:
             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' });
          

          【讨论】:

          • getFullName?() 不是有效的打字稿语法
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-19
          • 2020-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多