Getter Typescript 中反序列化对象的方法
Getter Methods on Deserialized Objects in Typescript
我们有各种 Http 调用我们的服务,return 对象的集合。在我们的 angular 应用程序中,typescript 将这些解释为适当的类型(如果指定),例如 Person:
export class Person{
public firstName: string;
public lastName: string;
public salutation: string;
}
假设我希望能够轻松地为这个用户构建一个问候语字符串,但我想成为一名优秀的程序员并且只做一次而不是多处。所以我创建了一个 getter 来检索它:
export class Person{
public firstName: string;
public lastName: string;
public salutation: string;
public get greeting(): string {
return salutation + " " + firstName + " " + lastName;
}
}
然而,当 typescript 反序列化它时,它缺少问候语 属性 的原型(它被设置为未定义)。我知道打字稿正在将 JSON 对象映射到它拥有的 class,并且映射对象上不存在任何缺失的 fields/properties(returning undefined 如果被调用)。解决此问题的最佳方法是什么?
作为我们如何调用服务的示例:
this.authHttp.post(this.url, user, params).then(
(res: Person) => {
console.log(res);
console.log(res.greeting);
}
);
您必须创建所谓的复制构造函数,它接收对象的所有字段:
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
现在你可以做
http.post(...)
.pipe(map(res => new Person(res.firstName, res.lastName)))
.subscribe(...);
当然,这有很多变体。你可以这样做
constructor(public firstName: string, public lastName: string) {}
例如,避免再次手动分配值。或者想出任何其他你想写的方式。这一切都归结为相同,即您需要实际创建 class 的 实例 而不是仅将 class 类型用作类型。
您的工作巧合,因为您访问的 属性 名称也由 .post
的响应提供。实际上,在 tsc
命令将其转换为 JavaScript 源后不再使用 TypeScript。因此,您会在 运行 时失去所有类型检查。
如果您要硬编码此作业,如下所示:
let me: Person = { firstName: 'Ian', lastName: 'MacDonald', salutation: 'Hello.' };
您将在尝试创建 JavaScript.
时收到 TypeScript 错误
Property 'greeting' is missing in type
'{ firstName: string; lastName: string; salutation: string; }'
but required in type 'Person'.ts(2741)
您在 class 上定义的任何函数也会出现同样的错误。这是因为 { ... }
不是 您的类型;它只有明确定义的内容。服务器响应的结果将遵循相同的分配规则,但问题不会出现(因为数据不存在)直到 运行 时间。
我建议在任何尝试使用服务器响应之前使用管道为自己构造一个 class 的实例,这样任何错误都可以在第一次联系时被捕获,而不是 10 秒后您最终尝试访问.save()
不存在的操作。
.post(...).pipe(map((incoming: any) => {
let person: Person = new Person();
person.firstName = incoming.firstName;
person.lastName = incoming.lastName;
person.salutation = incoming.salutation;
return person;
});
HTTP调用的响应不生成Person的对象class。响应实际上是一个普通的 JavaScript 对象,显然没有 Person class.
的 greeting() 方法
为了解决这个问题,您可以应用以下代码:
http.post(...)
.pipe(map(res => Object.assign(new Person(), res)))
.subscribe(...);
Object.assign(new Person(), res) 函数会将 res 的所有值复制到 Person 实例。在此映射之后,您将拥有一个真实的 Person 实例,其属性值从 http 调用返回的资源中复制。
我们有各种 Http 调用我们的服务,return 对象的集合。在我们的 angular 应用程序中,typescript 将这些解释为适当的类型(如果指定),例如 Person:
export class Person{
public firstName: string;
public lastName: string;
public salutation: string;
}
假设我希望能够轻松地为这个用户构建一个问候语字符串,但我想成为一名优秀的程序员并且只做一次而不是多处。所以我创建了一个 getter 来检索它:
export class Person{
public firstName: string;
public lastName: string;
public salutation: string;
public get greeting(): string {
return salutation + " " + firstName + " " + lastName;
}
}
然而,当 typescript 反序列化它时,它缺少问候语 属性 的原型(它被设置为未定义)。我知道打字稿正在将 JSON 对象映射到它拥有的 class,并且映射对象上不存在任何缺失的 fields/properties(returning undefined 如果被调用)。解决此问题的最佳方法是什么?
作为我们如何调用服务的示例:
this.authHttp.post(this.url, user, params).then(
(res: Person) => {
console.log(res);
console.log(res.greeting);
}
);
您必须创建所谓的复制构造函数,它接收对象的所有字段:
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
现在你可以做
http.post(...)
.pipe(map(res => new Person(res.firstName, res.lastName)))
.subscribe(...);
当然,这有很多变体。你可以这样做
constructor(public firstName: string, public lastName: string) {}
例如,避免再次手动分配值。或者想出任何其他你想写的方式。这一切都归结为相同,即您需要实际创建 class 的 实例 而不是仅将 class 类型用作类型。
您的工作巧合,因为您访问的 属性 名称也由 .post
的响应提供。实际上,在 tsc
命令将其转换为 JavaScript 源后不再使用 TypeScript。因此,您会在 运行 时失去所有类型检查。
如果您要硬编码此作业,如下所示:
let me: Person = { firstName: 'Ian', lastName: 'MacDonald', salutation: 'Hello.' };
您将在尝试创建 JavaScript.
时收到 TypeScript 错误Property 'greeting' is missing in type
'{ firstName: string; lastName: string; salutation: string; }'
but required in type 'Person'.ts(2741)
您在 class 上定义的任何函数也会出现同样的错误。这是因为 { ... }
不是 您的类型;它只有明确定义的内容。服务器响应的结果将遵循相同的分配规则,但问题不会出现(因为数据不存在)直到 运行 时间。
我建议在任何尝试使用服务器响应之前使用管道为自己构造一个 class 的实例,这样任何错误都可以在第一次联系时被捕获,而不是 10 秒后您最终尝试访问.save()
不存在的操作。
.post(...).pipe(map((incoming: any) => {
let person: Person = new Person();
person.firstName = incoming.firstName;
person.lastName = incoming.lastName;
person.salutation = incoming.salutation;
return person;
});
HTTP调用的响应不生成Person的对象class。响应实际上是一个普通的 JavaScript 对象,显然没有 Person class.
的 greeting() 方法为了解决这个问题,您可以应用以下代码:
http.post(...)
.pipe(map(res => Object.assign(new Person(), res)))
.subscribe(...);
Object.assign(new Person(), res) 函数会将 res 的所有值复制到 Person 实例。在此映射之后,您将拥有一个真实的 Person 实例,其属性值从 http 调用返回的资源中复制。