I am having a hard time narrowing an instance of a class to its discriminated union.
I have the following discriminated union:
interface ILoadableLoading<T> {
state: "Loading";
id: number;
}
interface ILoadableLoaded<T> {
state: "Loaded";
id: number;
item: T;
}
interface ILoadableErrored<T> {
state: "Error";
id: number;
error: string;
}
export type ILoadableDiscriminated<T> =
| ILoadableLoading<T>
| ILoadableLoaded<T>
| ILoadableErrored<T>;
type ILoadableState<T> = ILoadableDiscriminated<T>["state"];
And the following class:
class Loadable<T> {
state: ILoadableState<T> = "Loading";
id: number = 0;
item?: T | undefined;
error?: string | undefined;
}
Now how can I narrow an instance of that class to its respective ILoadableDiscriminated<T> union keeping some type safety (not using any)?
E.g. I have the following create method, and would like to return the discriminated union:
unction createLoadable<T>(someState: boolean): ILoadableDiscriminated<T> {
var loadable = new Loadable<T>();
if (someState) {
loadable.state = "Error";
loadable.error = "Some Error";
// Would like to remove this cast, as it should narrow it out from state + defined error above
return loadable as ILoadableErrored<T>;
}
if (loadable.state === "Loading") {
// Would like to remove this cast, as it should narrow it from state;
return loadable as ILoadableLoading<T>;
}
if (loadable.state === "Loaded" && loadable.item) {
// Would like to remove this cast, as it should narrow it from state;
return loadable as ILoadableLoaded<T>;
}
throw new Error("Some Error");
}
Sample can be found on: https://codesandbox.io/embed/weathered-frog-bjuh0
File: src/DiscriminatedUnion.ts
stateis a discriminant) but I'm not sure if narrowing on assignment follows the same path as type guarding. I'm a bit stumped... maybe someone else has more ideas? - jcalzsomeStateistrue- jcalz