这是我三周前问到的这个问题的延伸:Set the keys of an interface to the possible values of a different interface?
简短的版本是我具有以下类型定义
interface SuccessStatus {
type: 'success';
payload: string;
}
interface LoadingStatus {
type: 'loading';
}
interface ErrorStatus {
type: 'error';
error: string;
}
type RequestStatus = SuccessStatus | LoadingStatus | ErrorStatus;
以及以下映射的记录类型,以为每个上述状态定义一个具有“处理程序”的对象:
type RequestHandlerVisitor = Record<
RequestStatus["type"],
(status: RequestStatus) => void
>;
每个T
都有一个K
函数。
这将定义一个看起来像这样的对象:
const statusVisitor: RequestHandlerVisitor = {
"success": (status: RequestStatus) => { ... },
"loading": (status: RequestStatus) => { ... },
"error": (status: RequestStatus) => { ... },
}
现在,我要定义的是一个类似的类型,其中K
的值根据哪个键是T
而变化,因此它看起来像这样:
const statusVisitor: NewRequestHandlerVisitor = {
"success": (status: SuccessStatus) => { ... },
"loading": (status: LoadingStatus) => { ... },
"error": (status: ErrorStatus) => { ... },
}
在这种情况下,函数K
的第一个参数的值根据T
的不同而变化。
一种选择是像这样硬编码该类型:
interface NewRequestHandlerVisitor {
"success": (status: SuccessStatus) => void;
"loading": (status: LoadingStatus) => void;
"error": (status: ErrorStatus) => void;
}
在这种特定情况下可以满足我的需求,但是当我有更多的“状态”类型时就变得笨拙,每种类型都需要使用该类型的新条目。
有没有办法动态定义类似的东西?
谢谢!
答案 0 :(得分:2)
您可以使用自定义映射类型和Extract
条件类型来完成此操作:
interface SuccessStatus {
type: 'success';
payload: string;
}
interface LoadingStatus {
type: 'loading';
}
interface ErrorStatus {
type: 'error';
error: string;
}
type RequestStatus = SuccessStatus | LoadingStatus | ErrorStatus;
type RequestHandlerVisitor = {
[P in RequestStatus["type"]]: (s: Extract<RequestStatus, { type: P }>) => void
}