gpt4 book ai didi

typescript - TypeScript 中联合类型的相应子类型的泛型

转载 作者:行者123 更新时间:2023-12-05 05:49:30 26 4
gpt4 key购买 nike

假设我有一个联合类型,我正在使用类似 reducer 的 API 调用模式,看起来像这样:

type Action = {
request: {
action: "create user",
payload: { name: string, age: number },
},
response: { ok: true, message: "user created" },
} | {
request: {
action: "delete user",
payload: { id: number },
},
response: { ok: true, message: "user deleted" },
};

当我选择一个特定的 Action 时,我希望能够预测相应的 react 是什么类型安全。例如,如果我要创建这样的函数,我想强制我确实为每个请求返回正确的相应响应。我在输入类型的类型安全方面没有问题。我无法将输出链接到与输入类型相关的相应子类型。

function doAction<T extends Action>(request: T["request"]): T["response"] {
if (request.action === "create user") {
const userName = payload.user.name; // Here we're good for type safety 👍
return {
ok: true,
message: "user deleted", // This should error, but it doesn't 👎
};
} else {
const { id } = request.payload; // Again, we're good here for type safety 👍
return {
ok: true,
message: "user deleted", // Ok, but missing strong type safety here 👎
};
}
}

我如何表明我想要 ["request"] 中选择的对象类型的 ["response"] 部分,而不仅仅是任何 行动[“回应”]?

TypeScript Playground Link

我还希望在制作这样的中间件功能时能够链接对象的这两半,例如:

function<T extends Action>(req: Request<T["request"]>, res: Response<T["response"]>) {
if (req.body.action === "create user") {
res.send({ ok: true, message: "user deleted" }); // this should not be allowed
}
...

最佳答案

为了降低复杂性并提高类型安全性,值得在此处使用策略模式

考虑这个例子:

type Action = {
request: {
action: "create user",
payload: { name: string, age: number },
},
response: { ok: true, message: "user created" },
} | {
request: {
action: "delete user",
payload: { id: number },
},
response: { ok: true, message: "user deleted" },
};

type Strategy = {
[Prop in Action['request']['action']]: Extract<Action, { request: { action: Prop } }>['response']
}

const strategy: Strategy = {
'create user': { ok: true, message: "user created" },
'delete user': { ok: true, message: "user deleted" }
};

function doAction<T extends Action['request']>(request: T): Extract<Action, { request: T }>['response']
function doAction(request: Action['request']) {
return strategy[request.action]

}

// {
// ok: true;
// message: "user created";
// }
const createUser = doAction({
action: "create user",
payload: { name: 'string', age: 42 },
})


// {
// ok: true;
// message: "user deleted";
// }
const deleteUser = doAction({
action: "delete user",
payload: { id: 1 },
})

Playground

策略 - 创建 HashMap 数据结构,其中键是操作名称,值是函数的返回类型。

另外,我有overloaded doAction 函数以缩小返回类型。

关于typescript - TypeScript 中联合类型的相应子类型的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70653729/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com