Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

288
Views
Define a TypeScript function that will accept an argument that is a function that could have multiple signatures?

Looking for a way to define a function in TypeScript that will accept, as one of it's arguments, a function that may be of different signatures

const foo = (a: string, b: number) => {
  //do something
}

const bar = (a: number, b: string, c: boolean) => {
  //do something
}

const myDynamicFunction = (
  str: string,
  // I tried this, but no dice
  method: ((a: string, b: number) => void) | ((a: number, b: string, c: boolean) => void), 
  num: number,
  bool?: boolean
) => {
  if (bool) {
    method(num, str, bool)
  } else {
    method(str, num)
  }
}

myDynamicFunction(
  'string', foo, 5
)

myDynamicFunction(
  'string', bar, 5, true
)

I tried going down the "function overloads" rabbit hole, but that just left me where I started w/ essentially the same error of unexpected number of arguments.

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

I think you'd have to cast your method, because TypeScript cant figure this one out:

if (bool) {
    (method as (a: number, b: string, c: boolean) => void)(num, str, bool)
  } else {
    (method as (a: string, b: number) => void)(str, num)
  }
about 4 years ago · Juan Pablo Isaza Report

0

There were some subtleties that I couldn't get my head around at first, but breaking it down finally got me there. Typescript seems to have some difficulty disambiguating parameter types without first defining discreet type aliases.

We need to use a type predicate to determine, based on the value of bool, whether we are dealing with a call to a BAR like function.

When we do that, we still haven't narrowed the type of bool to be specifically boolean (another predicate would do the job also), but we know that's the case so we can use the ! non-null assertion to allow it to be passed to a method that requires boolean.

Playground Link

type FOO = (a: string, b: number) => void
type BAR = (a: number, b: string, c: boolean) => void

function isBAR(method: any, bool: boolean | undefined): method is BAR {
    return typeof method === 'function' && bool !== undefined
}

const foo = (a: string, b: number) => {
    //do something
}

const bar = (a: number, b: string, c: boolean) => {
    //do something
}

const myDynamicFunction = (
    str: string,
    method: FOO | BAR,
    num: number,
    bool?: boolean
) => {
    isBAR(method, bool) ? method(num, str, bool!) : method(str, num)
}

myDynamicFunction('string', foo, 5)
myDynamicFunction('string', bar, 5, true)
myDynamicFunction('string', bar, 5, false)
about 4 years ago · Juan Pablo Isaza Report

0

Improving on my previous answer.

This aims to provide static checking that the function passed to myDynamicFunction does have one of the expected shapes (FOO or BAR).

Note the err[x] methods at the end all produce compile failures, albeit with the slightly unhelpful message "cannot be assigned to 'never'"

Playground Link

type FOO = (a: string, b: number) => void
type BAR = (a: number, b: string, c: boolean) => void

function isFOO(method: any, bool: boolean | undefined): method is FOO {
    return typeof method === 'function' && bool === undefined
}

function isBAR(method: any, bool: boolean | undefined): method is BAR {
    return typeof method === 'function' && bool !== undefined
}

const foo = (a: string, b: number) => {
    console.log('foo', a, b)
}

const bar = (a: number, b: string, c: boolean) => {
    console.log('bar', a, b, c)
}

const myDynamicFunction = <T extends FOO | BAR>(
    str: string,
    method: T & (Parameters<T> extends Parameters<FOO> ? T : Parameters<T> extends Parameters<BAR> ? T : never),
    num: number,
    bool?: boolean
) => {
    if (isBAR(method, bool)) {
        method(num, str, bool!)  
    } else if (isFOO(method, bool)) {
        method(str, num)        
    } else {
        throw "Fatal"
    }
}

type T0 = Parameters<FOO>


myDynamicFunction('string', foo, 5)
myDynamicFunction('string', bar, 5, true)
myDynamicFunction('string', bar, 5, false)

const err1 = (a: string, b: {}): void => {}
myDynamicFunction('string', err1, 5, false)
const err2 = (a: string): void => {}
myDynamicFunction('string', err2, 5, false)
const err3 = (): void => {}
myDynamicFunction('string', err3, 5, false)
const err4 = (a: number, b: string, c: {}): void => {}
myDynamicFunction('string', err4, 5, false)
const err5 = (a: number, b: string, c: boolean, d: any): void => {}
myDynamicFunction('string', err5, 5, false)
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!