TypeScript:如何使用泛型键入 react-query useMutation onError?
TypeScript: How to type react-query useMutation onError with generic?
考虑自定义 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"
}
]
});
}
});
}
);
};
您已经声明了一个带有通用错误字段的挂钩,如果您不提供该参数,它将默认为一个字符串:
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
挂钩,其中 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"
}
]
});
}
});
}
);
};
您已经声明了一个带有通用错误字段的挂钩,如果您不提供该参数,它将默认为一个字符串:
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'
});
}