2017-09-08 22 views
0

Angular & TypeScriptを使用すると、GenericsとすべてのCompile-Goodnessを使用して、ある種の型安全性を保証できます。しかし、たとえばHTTPサービスを使用している場合、特定のオブジェクトを取得するのではなく、JSONを解析します。例えば、我々はそれをやって、いくつかの一般的な方法があります:私たちはJSONを取得するため、TypeScript:複雑なオブジェクトを再帰的に作成する

public get<T>(relativeUrl: string): Promise<T> { 
    const completeUrlPromise = this.createCompleteUrl(relativeUrl); 
    const requestOptions = this.createRequestOptions(ContentType.ApplicationJson, true); 
    return completeUrlPromise.then(completeUrl => { 
     return this.processResponse<T>(this.http.get(completeUrl, requestOptions)); 
    }); 
    } 

    private processResponse<T>(response: Observable<Response>): Promise<T> { 
    const mappedResult = response.map(this.extractData); 

    const result = mappedResult.toPromise(); 
    return result; 
    } 

    private extractData(res: Response): any { 
    let body; 
    if (!Array.isArray(res)) { 
     if (res.text()) { 
     body = res.json(); 
     } 
    } else { 
     body = res; 
    } 

    if (!JsObjUtilities.isNullOrUndefined(body)) { 
     return body; 
    } 

    return {}; 
    } 

を最終的には、ジェネリック型は、このよう無用です。ジェネリックオブジェクトにJSON以外のメソッドやプロパティがある場合、それらは失われます。このように見て

private processResponse<T>(response: Observable<Response>, ctor: IParameterlessConstructor<T> | null = null): Promise<T> { 
    let mappedResult = response.map(this.extractData); 

    if (ctor) { 
     mappedResult = mappedResult.map(f => { 
     const newObj = JsObjFactory.create(f, ctor); 
     return newObj; 
     }); 
    } 

    const result = mappedResult.toPromise(); 
    return result; 
    } 

そしてJsObjFactory: はこれを避けるために、私たちは本当にオブジェクトを作成するためにコンストラクタ関数を渡すために可能性を追加

export class JsObjFactory { 
    public static create<T>(source: any, ctorFn: IParameterlessConstructor<T>): T { 
    const result = new ctorFn(); 
    this.mapDefinedProperties(source, result); 

    return result; 
    } 

    private static mapDefinedProperties<T>(source: Object, target: T): void { 
    const properties = Object.getOwnPropertyNames(target); 

    properties.forEach(propKey => { 
     if (source.hasOwnProperty(propKey)) { 
     target[propKey] = source[propKey]; 
     } 
    }); 
    } 
} 

これは浅いオブジェクトに対してうまく機能しますが、プロパティーがコンストラクターを持つ複合タイプでもある場合は機能しません。実行時に型がないので、私は現在、kindahowプロパティを解析し、クラスが存在するかどうかを確認し、それらを作成することです。しかし、これは非常に誤りがちで扱いにくいようです。

私は常にこの問題を抱える唯一の人ではないのですが、私が気づいていないソリューションやTypeScript/JavaScriptの機能はここにありますか?

+0

[JSONオブジェクトでtypescriptオブジェクトを初期化するにはどうすればいいですか?](https://stackoverflow.com/questions/22885995/how-do-i-initialize-a-typescript-object-with-a-a- json-object)(そこには良い答えがあります) – jcalz

答えて

0

私はこのように個人的にはしませんが、あなたが探しているものかもしれません。

例:

Customer.ts

export interface ICustomer { 
    Id: number; 
    Name: string; 
    Orders: IOrder[]; 
    ... 
} 

export class Customer implements ICustomer { 
    public Id: number; 
    public Name: string; 
    public Orders: IOrder[]; 

    constructor(customer: Partial<ICustomer>) { 
     this.Id = customer.Id || 0; 
     this.Name = customer.Name || ''; 
     this.Orders = []; 
     customer.Orders.forEach((order: IOrder) => this.Orders.push(new Order(order))); 
    } 

    //some functions 
} 

Order.ts

export interface IOrder { 
    Id: number; 
    Weight: number; 
    Shipmentdate: string; 
} 

export class Order implements IOrder { 
    public Id: number; 
    public Weight: number; 
    public Shipmentdate: string; 

    constructor(order: Partial<IOrder>) { 
     this.Id = order.Id || 0; 
     this.Weight = order.Weight || 0; 
     this.Shipmentdate = order.Shipmentdate || ''; 
    } 

    //some functions 
} 

これはObjectことは知られていますインスタンス化を担当する(この場合はCustomerに)なるだろうあなたが渡す複雑な型。そして、Orderは、インスタンス化する複合型を持つことができます。

+0

ありがとう、試してみてください。質問は、JSONからちょうど名前以外のものを作成する方法を知るにはどうすればよいですか? –

+0

@MatthiasMüllerクラス自体は知っていますか?または私はあなたを誤解していますか? – Arg0n

関連する問題