I have following sample code that behaviour is not clear to me.
type A = {
field: string
}
type B = {
field: number
}
//I expect A | B is equivalent to field: A["field"] | B["field"]
type AORB = A | B
type AORBField = {
field: A["field"] | B["field"]
}
type BaseTypes = {
field: number | string
}
//Toggle between AORB and AORBField
type AB = AORB;
//type AB = AORBField;
//type AB = BaseTypes
const isA = (t: AB): t is A => {
return typeof t.field === "string"
}
const isB = (t: AB): t is B => {
return typeof t.field === "number"
}
const test = (x: AB) => {}
const testA = (x: A) => {}
const testB = (x: B) => {}
const testString = (x: string) => {}
const testNumber = (x: number) => {}
const getField = () => {
const val = Math.random();
return Math.random() % 2 ? val.toString(): val
}
const getDummyObject = () => {
const val = Math.random();
return { field: Math.random() % 2 ? val.toString(): val }
}
//Why error?
const ab: AB = {
//field: 1 //This will pass for AORB
//field: "string" //This will pass for AORB
field: getField() //This will pass for AORBFields
}
//Why error?
const abc: AB = getDummyObject();
if (isA(ab)){
const a: A = ab;
testString(a.field)
testNumber(a.field) //Expected err
testA(a)
test(ab)
}
else
{
const b: B = ab; //This will fail for AORBField and BaseTypes, but that is expected since else statement cannot figure out main type
testString(b.field) //Expected err
testNumber(b.field)
testB(b)
test(ab)
}
There is a typescript error on ab and abc assignment that is surprising to me. I expect following types are alike AORB = AORBField = BaseTypes at least in context of what we can assign to them. Obviously only AORB would correctly infer type on “If else” statement.
I’ve failed to find explanation in TS docs, could someone enlighten me here?