If you create a union type and then use if
statement to identify it's type TypeScript will let you use properties & functions specific to this type:
type A = {
type: "A",
func(): void
};
type B = {
type: "B"
};
type Union = A | B;
const test: Union = ...;
test.func(); // Error: func does not exist on type B
if (test.type === "A")
test.func(); // Works fine
Is it possible to make this union globally, by making union of two scopes? Something like this would be very nice:
declare global {
environment: "A",
funcA(): void
} | {
environment: "B",
funcB(): void
}
funcA(); // Doesn't work (environment could be B, and B doesn't have funcA)
if (environment === "A")
funcA(); // Works (environment is A)
else
funcB(); // Works (environment is B)
I tried searching for this, but couldn't find anything that meets my needs. Is there any specific syntax or any workarounds?
One approach is to use a destructured discriminated union, where you assign the environment
, funcA
, and funcB
variables as destructured from an object of a discriminated union type. Here's an example using a tuple:
declare const
[environment, funcA, funcB]:
["A", () => void, undefined] |
["B", undefined, () => void];
funcA(); // error!
if (environment === "A") {
funcA(); // okay
} else {
funcB(); // okay
}
That works because environment
is considered the discriminant property of a discriminated union. When you check it, then funcA
and funcB
will be narrowed accordingly.