Sagar Acharya
Sagar Acharya

Reputation: 13

TypeScript function overloading with generic types

I am trying to create a higher order function that takes a callback function and returns an anonymous function which in turn returns the result of callback function. The returned anonymous function takes a parameter called number (n). I use this parameter as a condition for the type of result that is returned by the anonymous function. Basically if number is greater than 1 return an array of results of callback function else return the result of callback function. But I can't seem to get this function overloading definitions work with generic types.

export type ReturnedFunctionType<T> = {
  (): T
  (n: number): T[]
  (n?: number): T | T[]
}

export function higherOrderFn<T> (cb: () => T): ReturnedFunctionType<T> {
  return function (n = 1) {
    if (n === 1) {
      return cb()
    } else {
      return Array(n).fill(null).map(_ => cb())
    }
  }
}

The error says:

Type '(n?: number) => T | T[]' is not assignable to type 'ReturnedFunctionType<T>'.
  Type 'T | T[]' is not assignable to type 'T[]'.
    Type 'T' is not assignable to type 'T[]'.

Can somebody explain me why can't I do this? Or how can I correctly type such function ?

Upvotes: 1

Views: 999

Answers (1)

L.A
L.A

Reputation: 455

I think you need to name your overloaded function. something like this should work

export function higherOrderFn<T> (cb: () => T) {
  function foo(n?: 1): T
  function foo(n: number): T[]
  function foo(n?: number): T | T[]   
   function foo(n = 1) {
    if (n === 1) {
      return cb()
    } else {
      return Array(n).fill(null).map(_ => cb())
    }
  }
  return foo;
}

const foobar = higherOrderFn(() => {})
const foo1 = foobar() // return type void
const foo2 = foobar(1) // return type void
const foo3 = foobar(2) // return type void[]

Playground

Upvotes: 2

Related Questions