我正在创建一个名为Loadable<T>
的泛型类,其中包含两个字段。一个名为state
,其中包含可加载资源的当前状态。第二个名称为data
,其中包含可加载资源的值。
state
被定义为"loading" | "loaded" | "error"
,我想根据当前data
的值来更改state
的类型。
例如,如果state
是"loading"
,则data
应该是null
。我无法弄清楚这样做的语法。
我创建了一个名为type
的{{1}},其定义为:
LoadableState<T, U>
传递的 type LoadableState<T, U> =
T extends "loaded" ? U :
T extends "loading" ? null :
T extends "error" ? string :
never;
的类型必须为T
。
这部分有效,但尝试以此定义"loaded" | "loading" | "error"
无效。
data
TypeScript引发以下错误:export class Loadable<T> {
public state: "loaded" | "loading" | "error" = "loading";
public data: LoadableState<state, T>;
// ^^^^^ Cannot find name 'state`
}
我尝试过的其他事情:
Cannot find name 'state'
我不确定这是否可行。如果不是,是否还有其他解决方案?
答案 0 :(得分:7)
我认为没有一种方法(或至少不是一种干净的方法)使一个类属性的类型依赖于另一个属性的当前值。
最好将这两个属性组合成一个对象:
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" }
}
尽管类包装器在这里实际上不是很有用,但您可能会考虑完全不使用类。
使用此类型时,Typescript将强制您在尝试访问数据之前检查state
:
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
}
}
此模式称为Discriminated Union,在Typescript中非常常用。