简体   繁体   English

如何在不丢失TypeScript类属性的情况下将JSON对象列表转换为TypeScript对象列表?

[英]How do I cast a list of JSON objects into a list of TypeScript objects without losing properties on the TypeScript class?

I have this Customer class: 我有这个Customer类:

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

In my controller I pull down a list of customers: 在我的控制器中,我下载了一个客户列表:

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

If it helps, getAll() looks like this: 如果有帮助,getAll()看起来像这样:

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

It's this statement that's causing me grief: this.customers = response.data; 这句话让我感到悲伤: this.customers = response.data;

But response.data is strongly typed, so shouldn't it "know" about Customer and name()? 但是response.data是强类型的,所以它不应该“知道”关于Customer和name()吗?

When I do that, of course I am overwriting my strongly typed array with the dumb JSON one, which doesn't have my name() method on it. 当我这样做的时候,当然我用哑的JSON覆盖我的强类型数组,它没有我的name()方法。

So how do I keep my name method without copying every property of every object in the list? 那么如何在不复制列表中每个对象的每个属性的情况下保留我的名称方法呢?

Is this bad design on my part? 这是我的坏设计吗? Having these read-only properties was really common in C#, but I'm a little new to the javascript world. 拥有这些只读属性在C#中非常常见,但我对javascript世界有点新鲜。 Should I be using a utility class instead? 我应该使用实用程序类吗?

My current work-around: 我目前的解决方法:

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

Feels wrong to build a whole new array and copy all those fields (in my real project Customer has many more properties). 构建一个全新的数组并复制所有这些字段感觉不对(在我的真实项目中,Customer有更多的属性)。

Edit: I've found a few related SO questions, such as Mapping JSON Objects to Javascript Objects as mentioned by @xmojmr. 编辑:我发现了一些相关的SO问题,比如@xmojmr提到的将JSON对象映射到Javascript对象 My question was specific to TypeScript and I was wondering if TypeScript had any facilities of its own that would generate the javascript to make this a non-issue. 我的问题是特定于TypeScript的,我想知道TypeScript是否有自己的任何设施可以生成javascript以使其成为非问题。 If that's not the case, and we're sure TypeScript doesn't aim to solve this class of problem, then we can regard this question as a duplicate. 如果情况并非如此,并且我们确信TypeScript不是为了解决这类问题,那么我们可以将此问题视为重复。

You're exactly right about what is happening. 你对发生的事情是完全正确的。 Typing in typescript mainly provides you with compiler checking. 键入typescript主要为您提供编译器检查。 Under the covers, everything compiles to JavaScript which isn't strongly typed. 在封面下,所有内容都编译为JavaScript,而不是强类型。

So, when you say: 所以,当你说:

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

all you are really doing is telling is telling the compiler "Hey, I'm pretty sure my api endpoint is going to return an array of Customer objects." 所有你真正在做的就是告诉编译器“嘿,我很确定我的api端点将返回一个Customer对象数组。” But as you know, it really just returns a "dumb JSON" array. 但是如你所知,它实际上只返回一个“哑的JSON”数组。

What you could consider doing, is creating an interface that describes the JSON object being returned by the API endpoint. 您可以考虑做的是创建一个描述API端点返回的JSON对象的接口。 Something like: 就像是:

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

And then getAll() becomes: 然后getAll()变为:

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

Then you could have a class who's constructor takes ICustomer as a parameter. 然后你可以让一个类的构造函数将ICustomer作为参数。 Or you could create a class with a static method that takes ICustomer and returns the "name". 或者您可以使用静态方法创建一个类,该方法接受ICustomer并返回“name”。

Obviously, what you are doing now works, but I think you're right to be looking for something that better communicates the intent. 显然,你现在正在做的事情是有效的,但我认为你正在寻找能够更好地传达意图的东西。

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

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