Since we have to cast our inputs variable as const, there's nothing to keep us from mistyping an input. Seems like we're basically trading type safety for the Builder inputs with type safety for our custom components. It would be nice if this lib exported a helper to have the best of both worlds.
Here's one way that seems to work:
import type { Input } from '@builder.io/sdk';
// Readonly only goes one level deep, so we need our own utility type
type DeepReadonly<T> =
T extends (infer R)[] ? DeepReadonlyArray<R> :
T extends Function ? T :
T extends object ? DeepReadonlyObject<T> :
T;
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
const inputs = [
{
name: 'tabs',
type: 'list',
subFields: [
{
name: 'label',
type: 'text',
defaultValue: 'New tab',
},
{
name: 'content',
type: 'uiBlocks',
defaultValue: [],
},
],
defaultValue: [
{
label: 'Tab 1',
content: [],
},
],
},
] as const satisfies DeepReadonly<Input[]>;
Maybe we could export type BuilderInputs = DeepReadOnly<Input[]> so users can just do as const satisfies BuilderInputs?
Since we have to cast our inputs variable
as const, there's nothing to keep us from mistyping an input. Seems like we're basically trading type safety for the Builder inputs with type safety for our custom components. It would be nice if this lib exported a helper to have the best of both worlds.Here's one way that seems to work:
Maybe we could
export type BuilderInputs = DeepReadOnly<Input[]>so users can just doas const satisfies BuilderInputs?