Reputation: 2465
I have a JavaScript codebase with several examples of the following (playground link here):
interface ComplexObject {
field1: string;
field2: boolean;
field3: number;
}
declare function getField1(): Promise<string>;
declare function getField2(): Promise<boolean>;
declare function getField3(): Promise<number>;
const promiseBuilder = function() : Promise<ComplexObject> {
//Not using Partial here results in a ts(2739) error that
//field1, field2, field3 are missing from type '{}'.
const result: Partial<ComplexObject> = {}
return new Promise(function (resolve, reject) {
getField1().then(function(field1){
result.field1 = field1;
return getField2();
}).then(function(field2){
result.field2 = field2;
if(field2) {
return getField3();
} else {
return Promise.resolve(0);
}
}).then(function(field3){
result.field3 = field3;
//result now has all the fields, but there's an error:
//Partial<ComplexObject>' is not assignable to 'ComplexObject'.
resolve(result);
}).catch(function(err) {
reject(err);
});
})
}
Without type annotations, this works just fine in JavaScript, but in TypeScript it has the errors indicated.
What is the canonical way to do something like this in TypeScript?
Upvotes: 1
Views: 262
Reputation: 2465
The closest found so far requires converting to the async style, using local const
s to hold the values temporarily, and assembling the entire object at once, like this (playground link here):
const asyncBuilder = async function() : Promise<ComplexObject> {
const field1 = await getField1();
const field2 = await getField2();
let field3 = 0;
if(field2) {
field3 = await getField3();
}
return { field1, field2, field3 };
}
However, that means a lot of rewriting what was previously valid code, so if there's a way to do it with less code rewriting, that would be good to know about!
Upvotes: 1