wise-white
wise-white4mo ago

What type safety can be achieved with Refine vs what can't?

New to refine, a couple of years of experience with typescript and react, many years using other type systems. Working through some simpe examples, I am running into many runtime errors that are not preceded by type errors or similar. E.g. I have a useForm that isn't passing all of the required fields for an update. It seems most of the documentation I've found seems to elide types. Is there any documentation about the extent to which types can be leveraged?
2 Replies
kapa.ai
kapa.ai4mo ago
Hi @jojohoho. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Refine is designed to leverage TypeScript to provide type safety, but there are some nuances and limitations to be aware of, especially when using hooks like useForm. Here’s a detailed look at what type safety can be achieved with Refine and what might be more challenging: Achievable Type Safety 1. Form Structure and Data Types: Refine allows you to specify types for form data and the data submitted to the DataProvider. This can help catch type errors at compile time rather than runtime. For example, you can use the useForm hook with type parameters to define the structure of your form and the data it handles.
import { HttpError } from "@refinedev/core";
import { useForm } from "@refinedev/react-hook-form";

interface User {
email: string;
user_metadata: {
display_name: string;
};
}

interface FormProps {
email: string;
userName: string;
}

export default function UserEdit() {
const {
refineCore: { queryResult, onFinish },
reset,
handleSubmit,
} = useForm<User, HttpError, FormProps>();

const user = queryResult?.data?.data;

useEffect(() => {
reset({
email: user?.email,
userName: user?.user_metadata?.display_name,
});
}, [reset, user]);

const handleSubmitInner = (formProps: FormProps) => {
onFinish({
email: formProps.email,
user_metadata: {
display_name: formProps.userName,
},
});
};

return (
<Edit
saveButtonProps={{
onClick: handleSubmit(handleSubmitInner),
}}
>
{/* ... */}
</Edit>
);
}

import { HttpError } from "@refinedev/core";
import { useForm } from "@refinedev/react-hook-form";

interface User {
email: string;
user_metadata: {
display_name: string;
};
}

interface FormProps {
email: string;
userName: string;
}

export default function UserEdit() {
const {
refineCore: { queryResult, onFinish },
reset,
handleSubmit,
} = useForm<User, HttpError, FormProps>();

const user = queryResult?.data?.data;

useEffect(() => {
reset({
email: user?.email,
userName: user?.user_metadata?.display_name,
});
}, [reset, user]);

const handleSubmitInner = (formProps: FormProps) => {
onFinish({
email: formProps.email,
user_metadata: {
display_name: formProps.userName,
},
});
};

return (
<Edit
saveButtonProps={{
onClick: handleSubmit(handleSubmitInner),
}}
>
{/* ... */}
</Edit>
);
}

This example shows how you can specify different types for the form structure (FormProps) and the data submitted to the DataProvider (User). 2. Type Support for Methods: Refine provides type support for various methods like register, getFieldState, and resetField when using useForm. This ensures that you get type errors if you misuse these methods.
import { type HttpError } from "@refinedev/core";

export interface IPost {
id: number;
title: string;
content: string;
status: "published" | "draft" | "rejected";
category: { id: number };
}

const form = useForm<IPost, HttpError, IPost>();

import { type HttpError } from "@refinedev/core";

export interface IPost {
id: number;
title: string;
content: string;
status: "published" | "draft" | "rejected";
category: { id: number };
}

const form = useForm<IPost, HttpError, IPost>();

Limitations and Challenges 1. Complex Type Mappings: There can be challenges when you need to map between different types, such as form data and the data structure expected by your backend. This can lead to type errors if not handled correctly, as seen in the example where FormProps needs to be converted to User. 2. Documentation and Examples: Some users have found that the documentation and examples provided by Refine may not always cover advanced type usage comprehensively. This can make it difficult to understand how to leverage TypeScript fully in more complex scenarios. For instance, the discussion in GitHub Issue 6137 (https://github.com/refinedev/refine/issues/6137) and GitHub Discussion 6136 (https://github.com/refinedev/refine/discussions/6136) highlights the difficulties in specifying type parameters for useForm to separate types for form structure and DataProvider submission. Resources - Refine useForm Documentation (https://refine.dev/docs/packages/list-of-packages/) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@865995958827352114> kapa.ai is still learning and improving, please let us know how it did by reacting below