Anyone know how to define a type for a function that has additional properties e.g.
foo({ name: 'john' })
foo.type
I assumed the following would work but TS believes that foo instead returns the function and is not callable itself with the payload argument.
type FuncWithType = {
(): (payload: { name: string}) => ({ type: string; payload: { name: string }});
type: string
}
Playground with above example and my faulty solution https://www.typescriptlang.org/play?#code/C4TwDgpgBAYgrgOwMYHUCWwAWAVc0C8UA3gFBRQAUAlAFyVgC[…]QgSJFYEUSgGOnhkdCxcSAUoAAZ3BgpScj5BOgByYAhRItcqbIA6RyA (edited)
CodePudding user response:
Please see related question.
Consider this example:
type FuncWithType = {
(): (payload: { name: string }) => ({ type: string; payload: { name: string } });
type: string
}
const foo: FuncWithType = () => {
return (payload) => ({
type: 'foo',
payload
})
}
foo.type='hello'
Please keep in mind, that your representation of FuncWithType
expects function which returns a function.
This syntax (): (payload: { name: string }) => ({ type: string; payload: { name: string } });
means that there is a function without arguments ()
which returns another function with payload
argument.
If you want to declare a type of non curried function you can use this syntax:
type FuncWithType =
& ((payload: { name: string }) => ({ type: string; payload: { name: string } }))
& {
type: string
}
const foo: FuncWithType = (payload) => ({
type: 'foo',
payload
})
foo.type = 'hello'
CodePudding user response:
You can use generics:
type FuncWithExtraProps<T> = T & {
<P>(payload: P): T & { payload: P };
}
declare const foo: FuncWithExtraProps<{ type: string }>;
foo.type
const result = foo({ name: 'john' });
and you can even restrict the type of the parameter(s):
type Fn<
Params extends unknown[] = any[],
Result = any,
> = (...params: Params) => Result;
type FuncWithExtraProps<ExtraProps, Payload> = (
Fn<
[payload: Payload],
ExtraProps & { payload: Payload }
>
& ExtraProps
);
declare const foo: FuncWithExtraProps<{ type: string }, { name: string }>;
foo.type
const result = foo({ name: 'john' });