Home > front end >  How does one type this default value in TypeScript?
How does one type this default value in TypeScript?

Time:09-17

Sorry for the vague title, but I don't know how to express this problem concisely.

Basically, I have the following code (with unimportant bits removed):

function identity<T>(value: T): T {
    return value;
}

function extent<T, K>(
    values: T[],
    map: (value: T) => K = identity // the '= identity' part gives an error
): [K, K] | undefined {
    let min;
    let max;

    // ... stuff ...

    return min === undefined || max === undefined ? undefined : [map(min), map(max)];
}

Where the default = identity value results in a compiler error.

I can remove the default value for the map parameter from the extent's signature and always provide one myself:

extent([5, 1, 3, 4, 8], x => x)

Which will work just fine, but I'd rather not supply the second parameter, unless I'm actually mapping the values from one type to another.

How do I type the indentity function so that it's accepted as the default value for extent's map parameter? I'm stuck on TypeScript 3.6 for the time being, if that matteres.

CodePudding user response:

Probably the best way to deal with this that maintains type-safety to the outside world is via overloads:

function extent<T>(values: T[]): [T, T] | undefined
function extent<T, K>(values: T[], map: (value: T) => K): [K, K] | undefined
function extent<T, K>(
  values: T[],
  map?: (value: T) => K 
): [K, K] | [T, T] | undefined {
  const actualMap = map ?? identity;
  let min;
  let max;

  // ... stuff ...

  return min === undefined || 
         max === undefined ? 
             undefined : 
             [actualMap(min), actualMap(max)];
}

CodePudding user response:

It's because of type error.

In map parameter you declare that this function will return the type of K but in the identity function you expect that to return the type of T so you can't assign it as a default value.

You could fix it like this: map: (value: K) => K = identity

CodePudding user response:

There is a conflict with T => K type of map and K => K type in identity function. Making identity less strict on types can help:

function identity<T>(value: T): any {
    return value;
}

or even

const identity = (x: any) => x;
  • Related