简体   繁体   中英

Type declaration for function with additional properties

Anyone know how to define a type for a function that has additional properties eg

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)

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<T, P> = T & Fn<[payload: P], T & P>;

declare const foo: FuncWithExtraProps<{ type: string }, { name: string }>;
foo.type
const result = foo({ name: 'john' });

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM