Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

291
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda