【问题标题】:How do I cast a list of JSON objects into a list of TypeScript objects without losing properties on the TypeScript class?如何在不丢失 TypeScript 类属性的情况下将 JSON 对象列表转换为 TypeScript 对象列表?
【发布时间】:2015-11-06 23:57:25
【问题描述】:

我有这个客户类:

export class Customer {
    id: number;
    company: string;
    firstName: string;
    lastName: string;

    name(): string {
        if (this.company)
            return this.company;
        if (this.lastName && this.firstName)
            return this.lastName + ", " + this.firstName;
        if (this.lastName)
            return this.lastName;
        if (this.firstName)
            return this.firstName;
        if (this.id > 0)
            return "#" + this.id;
        return "New Customer";
    }
}

在我的控制器中,我下拉了一个客户列表:

export class CustomersController {
    static $inject = ["customerService", "workflowService"];

    ready: boolean;
    customers: Array<Customer>;

    constructor(customerService: CustomerService, workflowService: WorkflowService) {
        customerService.getAll().then(
            (response) => {
                this.customers = response.data;
                this.ready = true;
            },
            () => {
                this.ready = true;
            }
        );
        workflowService.uiCustomer.reset();
    }
}
angular.module("app")
    .controller("CustomersController", ["customerService", "workflowService", CustomersController]);

如果有帮助,getAll() 看起来像这样:

    getAll(): ng.IHttpPromise<Array<Customer>> {
        return this.http.get("/api/customers");
    }

正是这句话让我伤心:this.customers = response.data;

但是 response.data 是强类型的,所以它不应该“知道” Customer 和 name() 吗?

当我这样做时,我当然会用愚蠢的 JSON 数组覆盖我的强类型数组,它上面没有我的 name() 方法。

那么如何在不复制列表中每个对象的每个属性的情况下保留我的 name 方法?

这是我的糟糕设计吗?拥有这些只读属性在 C# 中非常常见,但我对 javascript 世界有点陌生。我应该改用实用程序类吗?

我目前的解决方法:

this.customers = response.data.map(customer => {
    return angular.copy(customer, new Customer());
});

构建一个全新的数组并复制所有这些字段感觉不对(在我的真实项目中,客户有更多属性)。

编辑:我发现了一些相关的 SO 问题,例如 @xmojmr 提到的 Mapping JSON Objects to Javascript Objects。我的问题是针对 TypeScript 的,我想知道 TypeScript 是否有自己的工具可以生成 javascript 以使其成为非问题。如果不是这样,并且我们确定 TypeScript 的目的不是解决这类问题,那么我们可以认为这个问题是重复的。

【问题讨论】:

标签: javascript typescript


【解决方案1】:

您对正在发生的事情完全正确。在 typescript 中键入主要为您提供编译器检查。在幕后,一切都编译为非强类型的 JavaScript。

所以,当你说:

getAll(): ng.IHttpPromise<Array<Customer>> {
    return this.http.get("/api/customers");
}

您真正要做的只是告诉编译器“嘿,我很确定我的 api 端点将返回一个 Customer 对象数组。”但如您所知,它实际上只是返回一个“哑 JSON”数组。

您可以考虑创建一个接口来描述 API 端点返回的 JSON 对象。比如:

interface ICustomer {
    id: number;
    company: string;
    firstName: string;
    lastName: string;
}

然后getAll() 变为:

getAll(): ng.IHttpPromise<Array<ICustomer>> {
    return this.http.get("/api/customers");
}

然后你可以有一个类,它的构造函数将ICustomer 作为参数。或者,您可以使用静态方法创建一个类,该方法采用 ICustomer 并返回“名称”。

显然,您现在所做的工作有效,但我认为您正在寻找能够更好地传达意图的东西是正确的。

【讨论】:

  • TypeScript 有这方面的功能吗?例如,也许我告诉 TypeScript 我的 API 返回了一个客户,而是告诉它将结果转换为客户列表,它可以为我解决这个问题吗?如果这不是 TypeScript 可以/应该做的事情,那么我对您的回答感到满意,或者只是将我的问题称为重复。
  • 不幸的是,TypeScript 不允许您使用类型转换来实际更改对象的结构。这完全是关于使用类型来提供编译器检查错误。
  • 另一方面,使用类型确实可以提高代码的可读性和可维护性。通过选择好的类名,您可以使原本复杂的对象转换变得清晰。
猜你喜欢
  • 1970-01-01
  • 2021-03-04
  • 2020-12-11
  • 2014-05-17
  • 2018-03-26
相关资源
最近更新 更多