Я работаю над проектом TypeScript, где мне нужно обрабатывать ответы API, который может возвращать различные структуры в зависимости от случаев успеха или ошибки. Ответы вводятся как объединение, и я хочу динамически проверять свойства без жесткого кодирования их имен.
Я использую useMutation React Query для обработки процесса входа в систему. Вот как я настроил свой крючок:
import { useMutation } from "@tanstack/react-query";
import { api } from "@/lib/api";
import { InferRequestType, InferResponseType } from "hono";
import { useNavigate } from "@tanstack/react-router";
const login = api.auth.login.$post;
type LoginRequest = InferRequestType<typeof login>;
type LoginResponse = InferResponseType<typeof login>;
const loginFunction = async (
credentials: LoginRequest
): Promise<LoginResponse> => {
const res = await login(credentials);
if (!res.ok) throw new Error("Failed to login");
const json = await res.json();
return json;
};
export const useLoginMutation = () => {
const navigate = useNavigate();
const mutation = useMutation<LoginResponse, Error, LoginRequest>({
mutationFn: loginFunction,
mutationKey: ["auth", "login"],
onSuccess: (data) => {},
onError: (error) => {},
});
return mutation;
};
Вот как выводится LoginResponse:
type LoginResponse = {
success: boolean;
message: string;
} | {
success: boolean;
message: string;
} | {
success: boolean;
message: string;
accessToken: string;
}
Когда ответ имеет код состояния 401 или 403, я получаю сообщение об успехе и сообщении. Когда 201: успех, сообщение, токен доступа.
При использовании обработчика onSuccess в хуке useMutation я хочу, чтобы TypeScript понимал, что данные имеют accessToken без явного жесткого кодирования имен свойств. 401 или 403 вызывают ошибку в loginFunction, которая затем вызывает onError в useMutation.
для динамической обработки различных структур ответа вы можете использовать защиту типа, чтобы помочь TypeScript понять, какой тип объединения используется. Защита типа — это функция, которая проверяет, принадлежит ли объект определенному типу.
вот пример:
function hasAccessToken(response: LoginResponse): response is { success: boolean; message: string; accessToken: string } {
return 'accessToken' in response;
}
Вы можете использовать этот тип защиты в своем обработчике onSuccess.
что-то вроде этого, чтобы вы не жестко кодировали имена свойств...
onSuccess: (data) => {
if (hasAccessToken(data)) {
// TypeScript now knows that data has an accessToken property
console.info(data.accessToken);
}
}