qwerty qwerty
qwerty qwerty

Reputation: 744

Typescript does not recognize callback's param type

I have the following function and its callback type:

type Callbacks = {
    onSuccess: (a: string) => void;
};

function t(event: string, ...args: [...any, Callbacks]) {

}

It works as expected but one thing, onSuccess function has a string param but TS can't recognize it and says that it has any type but I explicitly set it to string.

t("eventName", "bobo", 123, {onSuccess: (asd) => {
    // "asd" is a string but TS says that it's an any
    // Parameter 'asd' implicitly has an 'any' type
}})

playground link

What should I change in order to let TS recognize the callback's params type because manually specifying them every time is tedious?

P.S. it's a simplified example of my problem

Upvotes: 6

Views: 459

Answers (1)

jcalz
jcalz

Reputation: 329228

This is currently a missing feature in TypeScript. A function whose parameter list has leading or middle rest elements does not seem to benefit from contextual typing of its input parameters when called. There is a request at microsoft/TypeScript#45972 to change this. It's (as of 2022-07-06) marked as "awaiting more feedback", so if you want to see this changed it wouldn't hurt to give it a 👍 and comment with your use case if you think it's compelling. It wouldn't necessarily help, but I wouldn't hurt.

In the meantime, if you want to work around it, you could make t() a generic function in a type parameter corresponding to the leading rest tuple. (The original pull request for leading/middle rest elements at microsoft/TypeScript#41544 mentions that generic types are better supported.)

That would look like

function t<T extends any[]>(event: string, ...args: [...T, Callbacks]) {}

And then it works as desired:

t("hello", "bobo", 123, {
    onSuccess: (asd) => asd.toUpperCase() // asd is seen as string
})

Playground link to code

Upvotes: 5

Related Questions