payload icon indicating copy to clipboard operation
payload copied to clipboard

validate Property on Fields for example TextField overrides the validate which breaks TS

Open dominikzogg opened this issue 1 year ago • 2 comments

Link to reproduction

No response

Payload Version

v3.0.0-beta.74

Node Version

v20.16.0

Next.js Version

14.2.5

Describe the Bug

The validate property is typed the following: validate?: Validate<string | string[], unknown, unknown, TextField>; This and all the others are wrong. It should like other properties depend on if its hasMany: true or false, like its solved for maxRows.

I made a custom field which only supports hasMany: false and i would either have to add multiple TS ignores or add validation logic that cannot be reached.

Reproduction Steps

Add a validate callback on any Field.

Adapters and Plugins

No response

dominikzogg avatar Aug 07 '24 06:08 dominikzogg

export type TextField = {
    admin?: {
        autoComplete?: string;
        components?: {
            Error?: ErrorComponent;
            Label?: LabelComponent;
            afterInput?: CustomComponent[];
            beforeInput?: CustomComponent[];
        };
        placeholder?: Record<string, string> | string;
        rtl?: boolean;
    } & Admin;
    maxLength?: number;
    minLength?: number;
    type: 'text';
    validate?: Validate<string | string[], unknown, unknown, TextField>;
} & ({
    /** Makes this field an ordered array of strings instead of just a single string. */
    hasMany: true;
    /** Maximum number of strings in the strings array, if `hasMany` is set to true. */
    maxRows?: number;
    /** Minimum number of strings in the strings array, if `hasMany` is set to true. */
    minRows?: number;
} | {
    /** Makes this field an ordered array of strings instead of just a single string. */
    hasMany?: false | undefined;
    /** Maximum number of strings in the strings array, if `hasMany` is set to true. */
    maxRows?: undefined;
    /** Minimum number of strings in the strings array, if `hasMany` is set to true. */
    minRows?: undefined;
}) & FieldBase;

validate should move to the union type related to hasMany

dominikzogg avatar Aug 07 '24 06:08 dominikzogg

Just confirming that the types for the validate property are still broken in beta.115.

linobino1 avatar Oct 17 '24 10:10 linobino1

validate should move to the union type related to hasMany

The validate property is now in the union with hasMany, but this doesn't completely solve the underlying problem unfortunately. TypeScript simply cannot infer the validate functions through our Fields[] union. This is what the Collection and Global types use to type their fields property. It struggles to conclusively narrow the types and falls back to any as a result. Here's a simplified example:

type TextField = {
  type: 'text';
} & (
  | {
      hasMany: true;
      validate?: (value: string[]) => true | string;
    }
  | {
      hasMany?: false | undefined;
      validate?: (value: string) => true | string;
    }
);

export type TextareaField = {
  maxLength?: number
  minLength?: number
  type: 'textarea'
  validate?: (value: string) => true | string
}

const singleField: TextField = {
  type: 'text',
  validate: (value) => { // Inferred as string
    if (value === 'hello') {
      return 'Cannot be hello';
    }
    return true;
  },
};

const multipleField: TextField = {
  type: 'text',
  hasMany: true,
  validate: (value) => { // Inferred as string[]
    if (value.length === 0) {
      return 'Cannot be empty';
    }
    return true;
  },
};

type Fields = (TextField | TextareaField)[]

const fields: Fields = [
  {
    type: 'text',
    validate: (value) => { // DOES NOT WORK!!!
      if (value === 'hello') {
        return 'Cannot be hello';
      }
      return true;
    },
  }
]

There is likely a different way we can structure this but it's not going to be straightforward. Might need to perform some TypeScript gymnastics here.

jacobsfletch avatar Jan 23 '25 17:01 jacobsfletch

Problem is persisting in 3.52.0

AndreaColombo-sesamo avatar Sep 10 '25 12:09 AndreaColombo-sesamo