Class-transformer: plainToClass assumes response is an array

Created on 8 Oct 2017  路  5Comments  路  Source: typestack/class-transformer

Given the following code:

getProposal(id: string) : Promise<Proposal> {
    const url = `${this.proposalsUrl}/${id}`;
    var headers = new Headers();
    this._authService.createAuthorizationHeader(headers);
    var options = new RequestOptions({ headers: headers });
    return this.http.get(url, options)
        .toPromise()
        .then(response => plainToClass(Proposal, response.json()));
}

I get the typescript error:

[ts]
Type 'Promise'.
Type 'Proposal[]' is not assignable to type 'Proposal'.
Property 'id' is missing in type 'Proposal[]'.

How did it conclude that the response is an array??

documentation

Most helpful comment

You are having this issue because Typescript does not know the type of response.json(). This is because plainToClass (and some other methods from class-transformer) has multiple signatures. From src/index.ts:

/**
 * Converts plain (literal) object to class (constructor) object. Also works with arrays.
 */
export function plainToClass<T, V extends Array<any>>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T[];
export function plainToClass<T, V>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T;
export function plainToClass<T, V>(cls: ClassType<T>, plain: V|V[], options?: ClassTransformOptions): T|T[] {
    return classTransformer.plainToClass(cls, plain as any, options);
}

Since Typescript cannot determine the appropriate signature, I assume it just picks the first one, hence why it's telling you that Proposal[] is expected.

To fix your problem, you simply need to explicitly declare the type of response.json() using as Proposal:

.then(response => plainToClass(Proposal, response.json() as Proposal));

And off you go :)

All 5 comments

You are having this issue because Typescript does not know the type of response.json(). This is because plainToClass (and some other methods from class-transformer) has multiple signatures. From src/index.ts:

/**
 * Converts plain (literal) object to class (constructor) object. Also works with arrays.
 */
export function plainToClass<T, V extends Array<any>>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T[];
export function plainToClass<T, V>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T;
export function plainToClass<T, V>(cls: ClassType<T>, plain: V|V[], options?: ClassTransformOptions): T|T[] {
    return classTransformer.plainToClass(cls, plain as any, options);
}

Since Typescript cannot determine the appropriate signature, I assume it just picks the first one, hence why it's telling you that Proposal[] is expected.

To fix your problem, you simply need to explicitly declare the type of response.json() using as Proposal:

.then(response => plainToClass(Proposal, response.json() as Proposal));

And off you go :)

While that works - it seems a bit redundant?

Hi there,
What about this issue?

Hello, I'm interested in this as well! Thanks!

To array:

plainToClass(Permission, <any[]>JSON.parse(response))

To single:

plainToClass(Permission, <any>JSON.parse(response))

^-- a little less redundant.

Was this page helpful?
0 / 5 - 0 ratings