Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

294
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda