Overriding title in RootProps makes Puck complain about data
Description
import { type Config, type Data, Puck } from "@measured/puck";
import type { UserGenerics } from "@measured/puck/dist/no-external";
type FooRootProps = {
title: number;
};
type FooComponents = {
Box: { size: number };
};
const testData = 0 as unknown as Data<FooComponents, FooRootProps>;
const testConfig = 0 as unknown as Config<{
components: FooComponents;
root: FooRootProps;
}>;
// this is ok
const y: UserGenerics<{ components: FooComponents; root: FooRootProps }> =
testData;
function TestComponent() {
// data has an Typescript error
return <Puck config={testConfig} data={testData} />;
}
The error is
Type
Data<FooComponents, FooRootProps>is not assignable to typePartial<Data<FooComponents, FooRootProps & DefaultRootFieldProps>>, since title isnumberand cannot be assigned tonumber & stringwhich isnever.
The issue is the following,
export type UserGenerics<
// ...
> = {
// ...
UserRootProps: UserParams["rootProps"] & DefaultRootFieldProps;
// ...
}
Environment
- Puck version: 0.20.0, 0.20.1. No issue in 0.19.3
- Typescript version: 5.9.2, 7.0.0 (tsgo)
Hey @knthmn!
I can replicate the issue. Just to add more context:
The problem occurs when you change the type of root.title from a string to something else. In that case, the data is not accepted by the Puck component and a type error is thrown. If you keep it typed as a string (the default), the data is accepted and no error occurs.
This happens because of the UserGenerics.UserRootProps type definition you’re pointing to. Since title becomes an intersection between two primitive types, it becomes never and it fails.
For the record, I recommend not importing directly from "/puck/dist", but instead from "/puck". The UserGenerics type is also exposed there.
import { type Config, type Data, Puck } from "@measured/puck";
type FooRootProps = {
title: number;
};
type FooComponents = {
Box: { size: number };
};
const testData: Data<FooComponents, FooRootProps> = { root: {}, content: [] };
const testConfig: Config<{
components: FooComponents;
root: FooRootProps;
}> = {
components: {
Box: {
fields: { size: { type: "number" } },
render: ({ size }) => <div>{size}</div>,
},
},
};
function TestComponent() {
// data has a TypeScript error
return <Puck config={testConfig} data={testData} />;
}