Home > database >  Typescript: Optional property based on generic
Typescript: Optional property based on generic

Time:01-15

I have a TypeScript type definition like this:

export type MyConfig<
    T extends MyObject = MyObject,
    R extends MyRegistry|undefined = undefined,
> = {
    title: string | null,
    objects: T[],
    registry: R,
};

By default, the registry field should be optional (undefined). But if you specify the type param, you must provide it.

But I have a problem using this, when the R generic param is set to undefined:

const a: MyConfig = { title: null, objects: [] }; // Doesn't work: Property 'registry' is missing but required
const b: MyConfig<MyObject, MyRegistry> = { title: null, objects: [], registry: {} }; // works ok
const c: MyConfig<MyObject, undefined> = { title: null, objects: [], registry: undefined }; // works ok
const d: MyConfig<MyObject, MyRegistry|undefined> = { title: null, objects: [], registry: undefined }; // works ok

How can I make the type definition of MyConfig accept the missing 'registry' property (like in example 'a')?

I have tried this, but then, the examples where 'registry' is required dont work anymore:

export type MyConfig<
    T extends MyObject = MyObject,
    R extends MyRegistry|undefined = undefined,
> = {
    title: string | null,
    objects: T[],
    registry?: R, // <-- I have tried marking it as optional.
};

CodePudding user response:

You can use a conditional type for the registry and mark it as never when you don't want it !

export type MyConfig<
  T extends MyObject = MyObject,
  R extends MyRegistry | undefined = undefined,
> = {
  title: string | null,
  objects: T[],
} & (R extends undefined ? { registry?: never } : { registry: R });

Playground

  • Related