DEV Community

Acid Coder
Acid Coder

Posted on • Edited on

Typescript Why You Should Avoid Explicit Function Generics If Possible

There are few reasons, the obvious reason is: optimal developer experience

An intelligence type do the most work for you, it is more automate and you write less code

But there is one very important reason: it does not work well with union

to understand this, observe the below example:

type SomeType = {
    name: string;
    quantity: number;
};
const someFunc = <Key extends keyof SomeType>(
    key: Key,
    value: SomeType[Key],
) => {
    // ...
};

// not explicit generics
someFunc("name", "John") // OK
someFunc("name", 10) // Error as desired
someFunc("quantity", "John") // Error as desired
someFunc("quantity", 10) // OK

// explicit generics
someFunc<"name" | "quantity">("name", 10) // wrong, but no error
Enter fullscreen mode Exit fullscreen mode

Image description

playground

now, to be fair, this is not developers fault and should be not developers responsibility

ideally TS should handle case like this correctly, but unfortunately we don't have much option

except with this magic utility...

type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true

type SomeType = {
    name: string;
    quantity: number;
};
const someFunc = <Key extends keyof SomeType>(
    key: IsUnion<Key> extends true ? "No Union!":Key,
    value: SomeType[Key],
) => {
    // ...
};

someFunc<"name" | "quantity">("name", 10) //  error as expected

// still works as normal
someFunc("name", "John") // OK
someFunc("name", 10) // Error as desired
someFunc("quantity", "John") // Error as desired
someFunc("quantity", 10) // OK
Enter fullscreen mode Exit fullscreen mode

Image description

playground

IsUnion

Though this is a legit solution, it is not the best solution. As you can see it only warn you about union but do nothing to the other value type. Ideal solution is to show error on the value 10.

it is also not fun to do this every time, so please avoid explicit function generic if possible

origin of the question and more case study

Top comments (0)