I don’t think there’s a way (or at least not a clean way) to have the type of one class property to depend on the current value of another property.
You’re better off combining both these properties into a single object:
type LoadState<T> = {
state: "loading",
} | {
state: "loaded",
data: T
} | {
state: "error",
data: string; // or maybe 'message'
}
export class Loadable<T> {
state: LoadState<T> = { state: "loading" }
}
Though the class wrapper isn’t actually very useful here, you might consider not using the class at all.
When using this type, Typescript will enforce that you check the state before trying to access data:
function handleLoadState<T>(loadState: LoadState<T>) {
loadState.data // ERROR, can't access data, since it might not exist
if(loadState.state === "loaded")
loadState.data // okay
}
}
This pattern is called a Discriminated Union and is quite commonly used in Typescript.