TypeScript error with react-portabletext block components in NextJS
react-portabletext component within NextJS/TypeScript project.
When I set up a basic example for block styling as shown in the readme:
const components = {
block: {
h1: ({children}) => <h1 className="text-2xl">{children}</h1>,
}
};
<PortableText value={body} components={components} />Type '{ block: { h1: ({ children }: { children: any; }) => Element; }; }' is not assignable to type 'Partial<PortableTextReactComponents>'.
Types of property 'block' are incompatible.
Type '{ h1: ({ children }: { children: any; }) => Element; }' is not assignable to type 'PortableTextBlockComponent | Record<string, PortableTextBlockComponent>'.
Type '{ h1: ({ children }: { children: any; }) => Element; }' is not assignable to type 'Record<string, PortableTextBlockComponent>'.
Property 'h1' is incompatible with index signature.
Type '({ children }: { children: any; }) => Element' is not assignable to type 'PortableTextBlockComponent'.
Type '({ children }: { children: any; }) => Element' is not assignable to type 'FunctionComponent<PortableTextComponentProps<PortableTextBlock<PortableTextMarkDefinition, ArbitraryTypedObject | PortableTextSpan, string, string>>>'.
Types of parameters '__0' and 'props' are incompatible.
Type 'PropsWithChildren<PortableTextComponentProps<PortableTextBlock<PortableTextMarkDefinition, ArbitraryTypedObject | PortableTextSpan, string, string>>>' is not assignable to type '{ children: any; }'.
Property 'children' is optional in type 'PortableTextComponentProps<PortableTextBlock<PortableTextMarkDefinition, ArbitraryTypedObject | PortableTextSpan, string, string>> & { ...; }' but required in type '{ children: any; }'.ts(2322)
[types.ts(32, 3): ]()The expected type comes from property 'components' which is declared here on type 'IntrinsicAttributes & PortableTextProps<any>'Any tips are appreciated.
This is a TypeScript type inference issue with @portabletext/react. The error occurs because TypeScript can't properly infer the component prop types when you define the components object inline without explicit typing.
The solution is to explicitly type your components object using the PortableTextReactComponents type from the library:
import { PortableText, PortableTextReactComponents } from "@portabletext/react";
const components: Partial<PortableTextReactComponents> = {
block: {
h1: ({children}) => <h1 className="text-2xl">{children}</h1>,
}
};
<PortableText value={body} components={components} />By adding the type annotation Partial<PortableTextReactComponents>, you're explicitly telling TypeScript what structure to expect, which resolves the type incompatibility error.
Why This Happens
The issue stems from how TypeScript infers types. When you define the components object without explicit typing, TypeScript infers that children is required based on your component signature ({children}) => .... However, the actual PortableTextComponentProps type from the library makes children optional, creating a type mismatch.
The Partial<PortableTextReactComponents> type tells TypeScript to expect the proper component structure where all props (including children) follow the library's type definitions.
Alternative Approaches
You can also be more specific about the props if you need access to other properties:
import type { PortableTextBlockComponent } from "@portabletext/react";
const components = {
block: {
h1: ((props) => <h1 className="text-2xl">{props.children}</h1>) as PortableTextBlockComponent,
}
};This pattern is particularly useful when you need to access the full value prop or other properties passed to your custom components, as documented in the @portabletext/react documentation.
The front-end renders fine locally because JavaScript doesn't enforce these type constraints at runtime—it's purely a TypeScript compile-time issue that prevents your Vercel build from succeeding. Adding the explicit type annotation resolves the build failure without changing any runtime behavior.
Show original thread1 reply
Was this answer helpful?
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.