Reputation: 3836
I have a generic function fetcher
which accepts a callback parameter. This callback will be executed in the fetcher
function later on (I'm using Vue composables pattern here). Further, these callbacks accepts different parameters as an argument. I've typed fetcher
callback that accepts "params" parameter as an union type of possible params. Then I can use this fetcher
function and pass callbacks with different parameters.
Code example:
type Param1 = {
a: string;
}
type Param2 = {
a: string;
b: string;
}
type Params = Param1 | Param2
declare function fetcher(func: (params: Params) => void): void
declare function testFunc(obj: Param2): void
fetcher(testFunc)
Typescript error:
Argument of type '(obj: Param2) => void' is not assignable to parameter of type '(params: Params) => void'.
Types of parameters 'obj' and 'params' are incompatible.
Type 'Params' is not assignable to type 'Param2'.
Property 'b' is missing in type 'Param1' but required in type 'Param2'.(2345)
How can I type fetcher
function and pass a callback with declared params, like Param1
or Param2
which fetcher
can accept?
Upvotes: 0
Views: 200
Reputation: 565
TLDR: declare function fetcher(func: (params: Param1 & Param2) => void): void
Explanation:
The declaration:
declare function fetcher(func: (params: Param1 | Param2) => void): void
Instructs the compiler that func must support both Param1 and Param2 types.
Remember:
{ a: string; b: string } | { a: string; } !== { a: string; } & { b?: string }
Type union for function arguments:
{a}|{a,b} != {a,b?}
If you want to tell the compiler that fetcher accepts either func(p: Param1)
or func(p: Param2)
you have two possibilities:
// 1:
declare function fetcher(func: (params: Param1 & Param2) => void): void
// 2:
declare function fetcher(func: ((p: Param1) => void) | ((p: Param2) => void)): void
And the second one is more semantically correct as it tell the compiler that functions with both arguments are welcome.
Upvotes: 1