react-jsonschema-form
react-jsonschema-form copied to clipboard
Typescript Examples don't work
Scratching my original post - better start with something straight from the docs.
EDIT: Straight from the docs, and using latest versions of everything:
import Form from "@rjsf/core";
import { customizeValidator } from "@rjsf/validator-ajv8";
import { TabTransition } from "../../components/layout/TabTransitions";
import { JSONSchemaType } from "ajv";
interface FormData {
foo: string;
bar: number;
}
type Schema = JSONSchemaType<FormData>;
const schema: Schema = {
type: "object",
properties: {
foo: { type: "string" },
bar: { type: "number" },
},
required: ["foo", "bar"],
};
export const Edit = () => {
const formData: FormData = {
foo: "",
bar: 0,
};
const validator = customizeValidator<FormData>();
return (
<TabTransition>
<Form<FormData, Schema> schema={schema} validator={validator} formData={formData} />
</TabTransition>
);
};
The line <Form<FormData, Schema> schema={schema} validator={validator} formData={formData} />
fails with:
Type 'Schema' does not satisfy the constraint 'JSONSchema7'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<FormData, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'JSONSchema7'.
Types of property '$defs' are incompatible.
Type 'Record<string, UncheckedJSONSchemaType<Known, true>> | undefined' is not assignable to type '{ [key: string]: JSONSchema7Definition; } | undefined'.
Type 'Record<string, UncheckedJSONSchemaType<Known, true>>' is not assignable to type '{ [key: string]: JSONSchema7Definition; }'.
'string' index signatures are incompatible.
Type 'UncheckedJSONSchemaType<Known, true>' is not assignable to type 'JSONSchema7Definition'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<Known, true>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'JSONSchema7Definition'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<Known, true>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'JSONSchema7'.
Types of property 'anyOf' are incompatible.
The type 'readonly UncheckedJSONSchemaType<Known, true>[]' is 'readonly' and cannot be assigned to the mutable type 'JSONSchema7Definition[]'.
Ok. Let's remove the generic hints so that it reads <Form schema={schema} validator={validator} formData={formData} />
. Error:
Type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }' is not assignable to type 'JSONSchema7'.
Types of property '$defs' are incompatible.
Type 'Record<string, UncheckedJSONSchemaType<Known, true>> | undefined' is not assignable to type '{ [key: string]: JSONSchema7Definition; } | undefined'.
Type 'Record<string, UncheckedJSONSchemaType<Known, true>>' is not assignable to type '{ [key: string]: JSONSchema7Definition; }'.
'string' index signatures are incompatible.
Type 'UncheckedJSONSchemaType<Known, true>' is not assignable to type 'JSONSchema7Definition'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<Known, true>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'JSONSchema7Definition'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<Known, true>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'JSONSchema7'.
Types of property 'anyOf' are incompatible.
The type 'readonly UncheckedJSONSchemaType<Known, true>[]' is 'readonly' and cannot be assigned to the mutable type 'JSONSchema7Definition[]'.
Even removing all other props (In case there are mismatches with inference) such as <Form schema={schema} />
yields the same error.
The only way I found to "fix" this is to use <Form<FormData, JSONSchema7> schema={schema as JSONSchema7} validator={validator} formData={formData} />
. But we would lose most of the types in the process...
@hickscorp So it looks like you are running into the fact that we have defined StrictRJSFSchema
as the json-schema
provided type. Since you are using the AJV generic type instead, what happens if you use a global type augmentation to enhance the StrictRJSFSchema
type to support JSONSchemaType<any>
? We hesitate to force support for the AJV generic type in our base implementation at this point since we want our utilities to be validator implementation independent.
@heath-freenome thanks, but I truly have no clue what you're asking me to do. How could I do this?
I think the problem we have is fairly clear by now that we've been struggling for a bit trying to leverage Typescript with RJSF without success.
This doesn't work:
<Form<FormData>
validator={validator}
liveValidate
noHtml5Validate
formData={formData}
schema={schema}
uiSchema={uiSchema}
fields={fields}
templates={{ ButtonTemplates }}
widgets={widgets}
onSubmit={onSubmit}
showErrorList="bottom"
disabled={isLoading}
/>
We have to force a cast, and we're loosing all the typings down the line:
<Form<FormData>
validator={validator}
liveValidate
noHtml5Validate
formData={formData}
schema={schema as JSONSchema7}
uiSchema={uiSchema}
fields={fields}
templates={{ ButtonTemplates }}
widgets={widgets}
onSubmit={onSubmit}
showErrorList="bottom"
disabled={isLoading}
/>
@hickscorp Sorry for the delay, missed your previous message. At what level are you needing the typing to be maintained? Do you have custom widgets, fields or templates?
@heath-freenome Thanks (once more :D)
We do have custom fields, widgets and templates - yes.
Ideally we would like to understand how to properly type the Form
component - not downtype it to JSONSchema7
or a supertype of our own schema.
We would expect that this way, we would get warnings at compile time on invalid custom widget typings etc.
@hickscorp Given that you are choosing to use the AJV 8 typing scheme, I'm not sure how to work around your situation except to force the typing. I've created this issue in the ajv validator to get them to extract their types into a separate repo so that we can support AJV types without being forced to pull in ALL of ajv into our utilities. Perhaps putting some weight into AJV issues that are blocking you/us may help it happen?
Just wanted to second this issue as we are in a similar situation. We use custom widgets, templates and would like to everything to be typed, the formData, schema, etc. It might be helpful to at least provide working Typescript examples in the documentation.
@zbayoff Can you help us and respond to the AJV issue?
Any updates on this issue? The current example in the Documentation does not work. The issue above ^ does not seem to have been addressed by AJV, and I'm not sure relying on them to split their repo will happen anytime soon. Is there an alternate way/package to achieve typed json form data and schemas?
@zbayoff I wish there was a simpler way to do this that didn't create a HARD link between RJSF utils and AJV. Aside from someone in this community doing the work and submitting it to AJV, we are at their mercy here. In all honesty, RJSF is still stuck on JSON Schema v7. The only other option is for us to CLONE the AJV types locally and then have to manually keep everything in sync (PAINFUL). Given that, are you willing to build a new package for json-schema-types
that steals their types and also support the JSONSchema7 type as well?
This is a sad situation to be in. It's a real shame because their JsonSchemaType is much more powerful than the RJSF one.