I was trying to create a function that returns an object with a "type" property that'll determine the type of response (Either TResA or TResB)
Basically this:
enum SYSTEM_TYPE {
A = 1,
B = 2
}
export interface IResCommon {
type: SYSTEM_TYPE;
}
export type TResA = {
name: string;
} & IResCommon;
export type TResB = {
age: number;
} & IResCommon;
export type TResAll = TResA | TResB;
// Don't know how to apply this:
export type TResCondition<T extends TResA & TResB> = T['type'] extends SYSTEM_TYPE.A ? TResA : TResB;
function run():TResAll /*TResCondition<T>*/{
const math = Math.floor(Math.random()*2) 1;
if (math === SYSTEM_TYPE.A) {
return { name: "foo", type: SYSTEM_TYPE.A}
} else {
return { age: 12, type: SYSTEM_TYPE.B}
}
}
var o = run()
if (o.type === SYSTEM_TYPE.A) {
// Should assume o as type TResA
console.log(o.name) //<--- Property 'name' does not exist on type 'TResAll'
} else {
// Should assume o as type TResB
console.log(o.age) // Property 'age' does not exist on type 'TResAll'
}
How can I correctly apply TResCondition
in order to avoid property 'X' is undefined after checking the value of o.type?
Here's a link to the typescript playground;
CodePudding user response:
You need to make the union a discriminated union. To do this you need to add the type
property, with the appropriate enum literal type to TResA
and TResB
:
export type TResA = {
name: string;
type: SYSTEM_TYPE.A;
} & IResCommon;
export type TResB = {
age: number;
type: SYSTEM_TYPE.B;
} & IResCommon;