简体   繁体   English

打字稿 - 为类成员设置默认值

[英]Typescript - set default value for class members

I have a simple model:我有一个简单的模型:

export class Profile extends ServerData {
  name: string;
  email: string;
  age: number;
}

When I am make a call to the server (Angular 4, $http) I often get the following response:当我调用服务器(Angular 4,$http)时,我经常得到以下响应:

{
  name: string;
  email: string;
}

The age property is missing.缺少age属性。

Is there any way to use my model and create a default age in case it is missing?有什么方法可以使用我的模型并创建默认年龄以防它丢失? I would prefer not to have to create 2 separate models if possible.如果可能,我宁愿不必创建 2 个单独的模型。

I don't want to create the age as an optional property - I need it, even if it is just with an incorrect default.我不想将年龄创建为可选属性 - 我需要它,即使它只是具有不正确的默认值。

UPDATE:更新:

This is the call I making to the server:这是我对服务器的调用:

results-manager.component.ts:结果-manager.component.ts:

this.resultsManagerService.getResults(this.config.request.action, this.pagingAndSorting, this.args).subscribe(
  results => {
    this.results = this.results.concat(results as Profile[]);

results-manager.service.ts:结果-manager.service.ts:

getResults(action: string, pagingAndSorting: PagingAndSorting, args: string[]): Observable<Profile[]> {
return this.apiService.callServer(
  pagingAndSorting,
  action,
  ...args );

} }

The request works and I receive the response, but even if I define the default values (as suggested by @msanford's answer) they get removed when I receive the response back in the component.请求有效并且我收到了响应,但是即使我定义了默认值(如@msanford 的回答所建议的那样),当我在组件中收到响应时,它们也会被删除。 Likewise if i add a constructor to the model (as per Mike Tung's answer).同样,如果我向模型添加构造函数(根据 Mike Tung 的回答)。

It seems like the backend response is completely overwriting the model - not just assigning the values.后端响应似乎完全覆盖了模型 - 而不仅仅是分配值。

How can I get it to just assign the values to the model and not remove the values it does not return?我怎样才能让它只将值分配给模型而不删除它没有返回的值?

Yes, easily , and you don't need to add a class constructor.是的,很容易,而且您不需要添加类构造函数。

export class Profile extends ServerData {
  name: string;
  email: string;
  age: number = 0;
}

The ability to define default values is one of the main things that differentiates aclass from an interface .定义默认值的能力是区classinterface的主要因素之一。

For this to work you need to call new Profile() somewhere in your code, otherwise a class instance won't be created and you won't have defaults set, because the above TypeScript will compile to the following JavaScript:为此,您需要在代码中的某处调用new Profile() ,否则将不会创建类实例并且您不会设置默认值,因为上述 TypeScript 将编译为以下 JavaScript:

var Profile = /** @class */ (function () {
    function Profile() {
        this.age = 0;
    }
    return Profile;
}());

So just using it for type assertion at compile-time isn't sufficient to set a default at run-time.因此,仅在编译时将其用于类型断言不足以在运行时设置默认值。

See it in action in the TypeScript Playground .TypeScript Playground 中查看它的运行情况。

The reason you're seeing overwriting properties is due to type erasure in TypeScript.您看到覆盖属性的原因是 TypeScript 中的类型擦除 TypeScript has no idea what types of objects are assigned to its variables during runtime. TypeScript 不知道在运行时将什么类型的对象分配给它的变量。 This would seem somewhat strange to you if you're coming not from a java / c# background.如果您不是来自 java/c# 背景,这对您来说似乎有些奇怪。

Because in the end , it's just JavaScript.因为最终,它只是 JavaScript。 And JavaScript doesn't enforce strict type checking.并且 JavaScript 不强制执行严格的类型检查。

In order to ensure that your profile objects always have an age property, you could create your own objects then copy over the values you get from the response.为了确保您的个人资料对象始终具有年龄属性,您可以创建自己的对象,然后复制从响应中获得的值。 This is the usual approach when it comes to wire format to domain object mapping.当涉及到域对象映射的有线格式时,这是通常的方法。

To do this first create your domain model, a Profile class with a default age property in this case.为此,首先创建您的域模型,在本例中为具有默认年龄属性的 Profile 类。

 export class Profile {
        constructor(
            public name: string,
            public email: string,
            public age: number = 0) { }
    }

Then map your response to the domain model.然后将您的响应映​​射到域模型。

this.resultsManagerService.getResults(this.config.request.action, this.pagingAndSorting, this.args).subscribe(
  results => {
    let res = (results as Profile[]).map((profile) => new Profile(profile.name, profile.email, profile.age));
    this.results = this.results.concat(res);
 });

You can't quite do this automatically, but you could set defaults for a function (possibly the class constructor):您不能完全自动执行此操作,但您可以为函数(可能是类构造函数)设置默认值:

function makeProfile({ name = '', email = '', age = 0 }) {
  const person = new Profile;
  person.name = name;
  person.email = email;
  person.age = age;
  return person;
}

Now if you call makePerson({ name: 'name', email: 'email' }) it will return a Person with age = 0 .现在,如果您调用makePerson({ name: 'name', email: 'email' })它将返回一个age = 0Person

You don't need to do much aside from use a constructor.除了使用构造函数之外,您不需要做太多事情。

export class Profile extends ServerData {
  name: string;
  email: string;
  age: number;

  constructor(name: string = '', email: string = '', age: number = null) {
    this.name = name;
    this.email = email;
    this.age = age;
  }
}

This will create default params for things you are missing.这将为您缺少的东西创建默认参数。

export class Cell {
    constructor(
        public name: string = "",
        public rowspan: number = 1,
        public colspan: number = 1
    ){ }
}

export class Table {
    public c1 = new Cell()
    public c2 = new Cell()
    public c3 = new Cell()
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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