measuredco / puck

The visual editor for React
https://puckeditor.com
MIT License
5.28k stars 322 forks source link

Type error when using `ObjectField` type #621

Closed the-code-raccoon closed 1 month ago

the-code-raccoon commented 1 month ago

Background

Puck version: 0.16.0

Current Behaviour

I have two components A and B. I want them both to have a title rendered with some settings (ex. text alignment, text size, etc). So I created a function as follows in a separate file that both component A and B can call.

export const titleField: ObjectField = {
  type: 'object',
  objectFields: {
    text: {
      type: 'text',
    },
    subtext: {
      type: 'text',
    },
  },
}

However when I assign titleField to title in the config for my components. I get the following type error

type ComponentAProps = {
  title: {
    text: string
    subtext: string
  }
}

const ComponentA: ComponentConfig<ComponentAProps>  = {
  defaultProps: {
    title: {
      text: "Main text",
      subtext: "Sub text"
    }
  },
  fields: {
    // Type error on the line below
    title: titleField()
  } 
}

With the following error

Type 'ObjectField' is not assignable to type 'Field<{ text: string; subtext: string; }>'.
  Type 'ObjectField' is not assignable to type 'ObjectField<{ text: string; size: string; }>'.
    Type 'ObjectField' is not assignable to type '{ type: "object"; objectFields: { text: Field<string>; size: Field<string>; }; }'.
      Types of property 'objectFields' are incompatible.
        Type '{ [x: string]: Field<any>; }' is missing the following properties from type '{ text: Field<string>; size: Field<string>; }': text, subtext

Please let me know if this isn't an issue and just an error on my end, thanks!

chrisvxd commented 1 month ago

Hi @the-code-raccoon - try either

  1. passing in the props to your ObjectField
  2. removing the explicit ObjectField type from your titleField, which will let TS infer the type

Example for 1

export const titleField: ObjectField<{ title: string; subtext: string }> = {
  type: 'object',
  objectFields: {
    text: {
      type: 'text',
    },
    subtext: {
      type: 'text',
    },
  },
}