TypeScript:如何使用泛型输入 react-query useMutation onError?
Posted
技术标签:
【中文标题】TypeScript:如何使用泛型输入 react-query useMutation onError?【英文标题】:TypeScript: How to type react-query useMutation onError with generic? 【发布时间】:2021-11-29 12:17:36 【问题描述】:考虑一个自定义的useSignUp
钩子,其中mutate()
函数需要一些字段(在此示例中为name
和email
):
export default function App()
const name = "David";
const email = "david@gmail.com";
const signupMutation = useSignUp();
return (
<button
onClick=() =>
signupMutation.mutate(
name, email ,
onSuccess: (result) =>
...
,
onError: (result) =>
// Wanted: result of type ErrorResult<"name" | "email">
);
>
Sign Up
</button>
);
在这种情况下,我希望onError
的结果为ErrorResponse<"name" | "email">
类型。但是,我得到了ErrorResponse<string>
。
这是为什么呢?我如何指示 TypeScript 根据传递的数据推断特定类型(即"name" | "email"
,而不是string
)?
这是我输入useSignUp
的方式:
type SuccessResponse =
userId: string;
;
type ErrorResponse<T> =
userId?: string;
formErrors?: Array<
field: T;
type: string;
>;
;
export const useSignUp = <T extends string>() =>
return useMutation<SuccessResponse, ErrorResponse<T>, Record<T, string>>(
(data) =>
return new Promise((resolve, reject) =>
// Some logic here to either return a success or an error response
if (Math.random() > 0.5)
resolve(
userId: "1234"
);
else
reject(
formErrors: [
field: "email", // I want TypeScript to complain if it's neither "name" nor "email"
type: "ALREADY_EXISTS"
]
);
);
);
;
【问题讨论】:
关于你的reject
签名,参数不能更改。请参阅this 答案。
@MishaMoroshko 你能提供可重现的例子吗?
【参考方案1】:
你已经声明了一个带有通用错误字段的钩子,如果你不提供参数,它默认为一个字符串:
export const useSignUp = <T extends string>() =>
return useMutation<SuccessResponse, ErrorResponse<T>, Record<T, string>>(...)
所以一定要覆盖它:
type Field = 'name' | 'email';
// ...
useSignUp<Field>();
如果要根据提交的值键入错误:
const mutatedValues =
name: "David",
email: "david@gmail.com"
;
const signupMutation = useSignUp<keyof typeof mutatedValues>();
onError: (result) =>
result.formErrors?.forEach((e) =>
const field = e; // field is 'name' | 'email'
);
【讨论】:
是否可以避免将泛型提供给useSignUp
,而让TypeScript 以某种方式提供给infer
?
@MishaMoroshko 理论上,我认为 Typescript 可以通过使来自 react-query
的 mutate()
函数知道数据的关键,基于 mutatedValues
推断 onError
回调的参数,但图书馆不支持它。它们只允许您单独覆盖 TData
或 TError
。
需要在 useMutation 调用中定义类型。你不能让 useMutation 根据你最终传递给mutate
的内容来推断它的类型。要么按照此处的建议显式传递泛型,要么进行与用户名/电子邮件相关的特定突变(无泛型),或者将字段直接传递给 useMutation(如果可用),以便您可以从中推断:const signupMutation = useSignUp( name, email );
。然后,您可以在没有参数的情况下调用.mutate()
,并关闭您传递给 useMutation 的内容。然后,推理应该起作用了。以上是关于TypeScript:如何使用泛型输入 react-query useMutation onError?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Typescript 中正确使用 React.lazy() 来导入带有泛型类型参数的反应组件?
如何使用带有 Typescript 的泛型将中继(graphql)连接映射到边缘节点