[英]Type functions based on property in object
我正在尝试正确键入接口/对象,以便可以为具有特定类型的每个对象创建函数。 我不知道如何尝试更好地解释它,所以我会给你一些代码。
这是我的界面:
export interface Activity {
id: string;
metaData:
| {
type: "createTask";
data: { taskId: string; taskName: string; user: string };
task: string;
taskName: string;
}
| {
type: "deleteTask";
data: { taskName: string; user: string };
task: string;
taskName: string;
}
| {
type: "updateTask";
data: { taskId: string; taskName: string; user: string };
task: string;
taskName: string;
}
| {
type: "createScenario";
data: {
scenarioId: string;
scenarioName: string;
taskName: string;
user: string;
};
task: string;
taskName: string;
}
| {
type: "updateScenario";
data: { scenarioId: string; scenarioName: string; user: string };
task: string;
scenario: string;
taskName: string;
}
| {
type: "deleteScenario";
data: { scenarioName: string; user: string };
task: string;
taskName: string;
};
}
现在,我想从这个界面为每种不同类型的活动键入一个函数,以便我可以根据类型查找该函数。
这是我尝试过的:
export const activityFormatFunctions: Record<
Activity["metaData"]["type"],
(activity: Activity) => string
> = {
createScenario: (activity) => {
return ""
},
createTask: (activity) => {
return ""
},
deleteScenario: (activity) => {
return ""
},
deleteTask: (activity) => {
return ""
},
updateScenario: (activity) => {
activity.metaData.data.scenarioName;
return ""
},
updateTask: (activity) => {
activity.metaData.data.taskName;
return ""
},
};
问题是“活动”参数没有缩小到具有匹配类型的活动,因此我只能访问所有不同活动类型之间的公共属性。
在上面的示例中,我希望能够在updateScenario
场景函数中访问scenarioName
名称,因为 Activity 接口说它有一个scenarioName
名称
{
type: "updateScenario";
data: { scenarioId: string; scenarioName: string; user: string };
task: string;
scenario: string;
taskName: string;
}
为了便于阅读,我更喜欢在单独的接口中声明每个 Activity,并声明一个联合类型,以获得固定长度的可能性。
解决方案的很大一部分在于包含函数的对象的类型,并找到相应的联合类型。
type FindByType<Union, Type> = Union extends { type: Type } ? Union : never;
type MetadataMap = {
[K in Activity<TasksUnion>["metaData"]["type"]]: (activity: Activity<FindByType<TasksUnion, K>>) => string
}
export interface Activity<T extends TasksUnion> {
id: string;
metaData: T
}
type TasksUnion =
| CreateTask
| DeleteTask
| UpdateTask
| CreateScenario
| UpdateScenario
| DeleteScenario
type TaskType =
| "createTask"
| "deleteTask"
| "updateTask"
| "createScenario"
| "updateScenario"
| "deleteScenario"
interface BaseTask {
type: TaskType;
}
interface CreateTask extends BaseTask {
type: "createTask";
data: { taskId: string; taskName: string; user: string };
task: string;
taskName: string;
}
interface DeleteTask extends BaseTask {
type: "deleteTask";
data: { taskName: string; user: string };
task: string;
taskName: string;
}
interface UpdateTask extends BaseTask {
type: "updateTask";
data: { taskId: string; taskName: string; user: string };
task: string;
taskName: string;
}
interface CreateScenario extends BaseTask {
type: "createScenario";
data: {
scenarioId: string;
scenarioName: string;
taskName: string;
user: string;
};
task: string;
taskName: string;
}
interface UpdateScenario extends BaseTask {
type: "updateScenario";
data: { scenarioId: string; scenarioName: string; user: string };
task: string;
scenario: string;
taskName: string;
}
interface DeleteScenario extends BaseTask {
type: "deleteScenario";
data: { scenarioName: string; user: string };
task: string;
taskName: string;
};
// Everything correctly typed 👌🏻
export const activityFormatFunctions: MetadataMap = {
createScenario: (activity) => {
return ""
},
createTask: (activity) => {
return ""
},
deleteScenario: (activity) => {
return ""
},
deleteTask: (activity) => {
return ""
},
updateScenario: (activity) => {
activity.metaData.data.scenarioName;
return ""
},
updateTask: (activity) => {
activity.metaData.data.taskName;
return ""
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.