Home > database >  Typescript conditional function signature - based on boolean in option
Typescript conditional function signature - based on boolean in option

Time:09-30

Edited with partial function implementation that seems relevant:

I have this function:

mergeArrayElement<T>(
  array: T[],
  element: T | PartialDeep<T>,
  options?: {
    overwriteMerge?: boolean
  }
) {
  const index = list.findIndex(...);
  if (index > -1) {
    if (options.overwriteMerge) {
      list[index] = element; // type error can't assign PartialDeep<T> to T.
    } else {
      list[index] = deepmerge(list[index],element);
    }
  }
}

This function takes an element of partial type T, finds the target element in the array with some irrelevant logic, and merges it.

I want this function to have an option, that does the same thing, but instead of merging it just overwrites the element, I call it overwriteMerge but in reality, there is no merging done with it.

I want that when options overwriteMerge is given as true, the element will be required and type-checked to be T (and recognized as such in the function by typescript), And when overwriteMerge is false (or not given) then the element will have to be PartialDeep<T>.

Is such a thing possible with typescript or do I need another function? If I'm just regular merging the elements I'm okay with the object just being a partial type of the objects in the list. But If I'm simply overriding the element in the array, I want it to be the exact same type of array.

CodePudding user response:

Use Method Overloading

For the seek of example DeepPartial has been replaced with Partial

function mergeArrayElement<T>(array: T[], element: T, options?: { overwriteMerge?: true });
function mergeArrayElement<T>(array: T[], element: Partial<T>, options?: { overwriteMerge?: false });
function mergeArrayElement<T>(
    array: T[],
    element: T | Partial<T>,
    options?: { overwriteMerge?: boolean }
) {
    if (options?.overwriteMerge) {
        // implementation 1
    } else {
        // implementation 2
    }
}

This will result in

type X = { a: number, b: number };
mergeArrayElement<X>([], { a: 1, b: 2 }, { overwriteMerge: true })
mergeArrayElement<X>([], { a: 1 }, { overwriteMerge: true }) // invalid
mergeArrayElement<X>([], { a: 1, b: 2 }, { overwriteMerge: false })
mergeArrayElement<X>([], { a: 1 }, { overwriteMerge: false })
  • Related