Är det möjligt att villkorligt kräva en egenskap i ett Typescript-gränssnitt


Säg att jag har följande gränssnitt:

interface updateOptions {
  updateAll: boolean;
  fields: string[];
}

Finns det ett sätt att göra updateAll obligatoriskt när Fields inte tillhandahålls och vice versa, eller är detta något som måste göras villkorligt i implementeringen?

Svar #1

Använd märkt unionstyp:

type UpdateOptions =
  | {updateAll: true}
  | {updateAll: false, fields: string[]}

På detta sätt kan du bara initiera {updateAll: true} eller {updateAll: false, fields: ['someField', /*...*/]}

Tekniskt sett behöver unionen inte ha en tagg (boolean updateAll), men då behöver du definiera en typvakt för att testa vilken typ som används i en viss gren (jag antar att någonstans i din kod kommer du göra if (options.updateAll) {/* ... */}):

type UpdateAllOptions = {updateAll: true}
type UpdateSomeOptions = {fields: string[]}
type UpdateOptions = UpdateAllOptions | UpdateSomeOptions

// See https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
const isAllOptions = (options: UpdateOptions): options is UpdateAllOptions =>
  (options as any).updateAll === true

Relaterade artiklar