plainToClass assumes response is an array
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<Proposal[]>' is not assignable to type 'Promise<Proposal>'. 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??
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.
Edit: Just came here in 2024 and chose one of the higher in the thread (and slightly redundant) answers, not realizing I'd found a better way in 2019 :D