我有一个简单的模型:
export class Profile extends ServerData {
name: string;
email: string;
age: number;
}
当我打电话给服务器(Angular 4,$ http)时,我经常得到以下回复:
{
name: string;
email: string;
}
缺少age
属性。
有没有办法使用我的模型并创建一个默认的年龄,以防它丢失? 如果可能的话,我宁愿不必创建2个单独的模型。
我不想将age作为一个可选属性创建 - 我需要它,即使它的默认值不正确。
更新:
这是我对服务器的调用:
结果的manager.component.ts:
this.resultsManagerService.getResults(this.config.request.action, this.pagingAndSorting, this.args).subscribe(
results => {
this.results = this.results.concat(results as Profile[]);
结果的manager.service.ts:
getResults(action: string, pagingAndSorting: PagingAndSorting, args: string[]): Observable<Profile[]> {
return this.apiService.callServer(
pagingAndSorting,
action,
...args );
}
请求有效并且我收到了响应,但即使我定义了默认值(如@ msanford的回答所示),当我在组件中收到响应时,它们也会被删除。同样,如果我在模型中添加一个构造函数(根据Mike Tung的回答)。
似乎后端响应完全覆盖了模型 - 而不仅仅是分配值。
如何才能将值分配给模型而不删除它不返回的值?
答案 0 :(得分:5)
The reason you're seeing overwriting properties is due to type erasure in TypeScript. TypeScript has no idea what types of objects are assigned to its variables during runtime. This would seem somewhat strange to you if you're coming not a java / c# background.
Because in the end , it's just JavaScript. And JavaScriptdoesn't enforce strict type checking.
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.
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);
});
答案 1 :(得分:3)
是的,轻松,您不需要添加类构造函数。
export class Profile extends ServerData {
name: string;
email: string;
age: number = 0;
}
定义默认值的能力是区分class
和interface
的主要因素之一。
为了实现此功能,您需要在代码中的某处调用new Profile()
,否则无法创建类实例并且您不会设置默认值,因为上面的TypeScript将编译为以下JavaScript:
var Profile = /** @class */ (function () {
function Profile() {
this.age = 0;
}
return Profile;
}());
因此,只需在编译时将断言用于断言就足以在运行时设置默认值。
在TypeScript Playground中查看它。
答案 2 :(得分:1)
你不能自动完成这项工作,但你可以设置一个函数的默认值(可能是类构造函数):
function makeProfile({ name = '', email = '', age = 0 }) {
const person = new Profile;
person.name = name;
person.email = email;
person.age = age;
return person;
}
现在,如果您致电makePerson({ name: 'name', email: 'email' })
,它将返回Person
age = 0
。
答案 3 :(得分:1)
除了使用构造函数之外,您不需要做太多工作。
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;
}
}
这将为您缺少的东西创建默认参数。
答案 4 :(得分:0)
find node_modules \
-type f \
-name package.json \
-exec jq -r '._resolved' {} \; \
| sort \
| uniq