I'm trying to write a function that creates an object with all the common attributes of a union type but as far as I can tell it is not possible without a FlowFixMe. Here's an example
type AType = "a";
type BType = "b";
type CType = "c";
type AObj = {
type: AType,
common1: boolean,
common2: boolean,
}
type BObj = {
type: BType,
common1: boolean,
common2: boolean,
}
type CObj = {
type: CType,
common1: boolean,
common2: boolean,
unique?: string
}
type ObjType = AType | BType | CType;
type XObj = AObj | BObj | CObj;
function createObj(type: ObjType): XObj {
const myObj: XObj = {
type: type,
common1: true,
common2: false,
};
return myObj;
}
const myType: ObjType = "b";
const obj = createObj(myType);
The error I get is this
28: const myObj: XObj = { ^ Cannot assign object literal to `myObj` because: [incompatible-type] Either string literal `b` [1] is incompatible with string literal `a` [2] in property `type`. Or string literal `a` [1] is incompatible with string literal `b` [3] in property `type`. Or string literal `a` [1] is incompatible with string literal `c` [4] in property `type`.
References:
27: function createObj(type: ObjType): XObj {
^ [1]
6: type: AType,
^ [2]
12: type: BType,
^ [3]
18: type: CType,
^ [4]
You can test this on Try Flow
Flow is stricter than TypeScript.
You will need to use type guards to construct an object of each type:
function createObj(type: ObjType): XObj {
const defaultObj = {
common1: true,
common2: false,
}
if (type === "a") return { type, ...defaultObj };
if (type === "b") return { type, ...defaultObj };
if (type === "c") return { type, ...defaultObj, unique: "foobar" };
throw new TypeError(`Unknown type: ${type}`);
}
It seems verbose (and repetitive), but it's required.