davedbase / builderio-type-extensions

A package that makes inferring Builder types easy.
MIT License
11 stars 1 forks source link

Type safety for `inputs` const #1

Open cbejensen opened 1 year ago

cbejensen commented 1 year ago

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?

davedbase commented 1 year ago

Hmmm, I would definitely like to explore this. Would you mind submitting a PR? I'll give it a spin and released it under a next tag then get some feedback from a couple projects I know that are using this utility. :)