Home > database >  Type declaration for function with additional properties
Type declaration for function with additional properties

Time:12-15

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'

Playground

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:

TS Playground link

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):

TS Playground link

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' });
  • Related