#Can you change the call signature of a function based on whether a generic is undefined?

33 messages · Page 1 of 1 (latest)

daring storm
#

This is a simplified version of the scenario I'm contending with written in psuedo code.

function MyHOF<Payload extends object | undefined>(config: {
   payload?: Payload
}) {
    
    // return this if payload isn't configured
    return (config?: {options: any}) => any
    // return this if payload signature is provided
    return (config: {options: any, payload: Payload}) => any
}

I've made several attempts to write this and come up with overly complicated type signatures that don't work. Do I need to do something along the lines of:

type DoAction<Payload> = Payload extends undefined
? { (config?: {options: any}): any }
: { (config: {options: any, payload: Payload}) }
lone valley
#

What about function overload?

mighty summit
#

but yeah overloads are a way better idea

daring storm
#

@lone valley Are you saying conditionally create the options and then use overloads to determine the function's signature?

type Config<Payload> = Payload extends undefined
? {options: any}
: {options: any, payload: Payload}

type DoAction = {
  (config?: {options: any}): any
  (config: {options: any, payload: Payload}): any
}

const doAction: DoAction = <Payload>(config?: Config<Payload>) => undefined
lone valley
#

I don't think Config<Payload> is even used anymore then?

#

You can just do:

type DoAction = {
  (config?: {options: any}): any
  <T>(config: {options: any, payload: T}): any
}
#

Your doAction arrow function can have whatever type that's convenient for implementation.

mighty summit
daring storm
#

I think that my contrived example didn't fully illustrate the issue. What I ended up with was this:

type WithParams<TParams> = TParams extends undefined ? {}
    : { params: TParams };

type WithPayload<TPayload> = TPayload extends undefined ? {}
    : { payload: TPayload };

type Config<TParams, TPayload> = {
    axios?: AxiosRequestConfig;
} & WithParams<TParams> &
    WithPayload<TPayload>;

type DoFetch<TParams, TPayload, TResponse> = TParams extends undefined
    ? TPayload extends undefined
        ? { (config?: Config<undefined, undefined>): TResponse }
        : { (config: Config<undefined, TPayload>): TResponse }
    : TPayload extends undefined
    ? { (config: Config<TParams, undefined>): TResponse }
    : { (config: Config<TParams, TPayload>): TResponse };

I feel like there's a better way, but this works the way I wanted it to. doFetch is nested inside a HOF that receives a default configuration object where all of these types are inferred. The doFetch config and call signature shapes are tightly coupled to the shape of the default configuration.

#

If TParams or TPayload are defined, then you HAVE to provide a config to doFetch that includes those, otherwise it's optional (as a passthrough for the axios config).

lone valley
#

You are only giving bits and pieces each time and the conversation has to keep going back and forth to fish out more information.

daring storm
#

@lone valley Here's the current iteration of the code.
https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAQwB7AgZwDRwN5wIIrpYGpoBKApgI4CuFaMAwhAHYBmwA5lgLIUwALCABNihcvUgs0FOAF84bKBBBwARMlJqA3AChQkWDjgAveYuWqA5CZFXdumAE8wsgKpQANgDEEAYxhoJwAeABUABQQoBBA0AD44AF44AAowKJi0AC44CIzYgEokhIYoYBZOPUcXWUZPYAoWGEjo2ODdOFzIp08IBGE4CiQYRuE0OAAtEQA6KeFQmrgAHzgaFmEKDhYKUQ7cyjQpGUHh0fG52ZEF12XV9c3ynYw9vNbx5LWNrZ3dBOSAeRAwBgwRI6EotHoTFYHG46hoXjUtzUIH4QmEagSADIcHtUYIRDk+AThHpOgjPDlXpkTiN1uNPg9tgMAPxwUrlThwHIeHz+QJQELU2JxMlwdI9PrCADKfgEFBACBZVO6vX6YqgklYMll8sVyv2WukFD0ciqzhuAHVgQIWpkwnaRUkuvlxkM6WM7l9HqycAocrh0m8Va75ObFtbBKqpQ6EJL+n8XfGBu6zl6mT9OmzsHI9gHxXG1cIQ8naWmLnNrrI2Rcq-82LHkwkctsAG4UKBhhwW2owrixt5YPJN53YPaadAGsESSEMZjsLimuA4yO210DzLYvar6P9RtF0XdxYAEQg3n4co3sSHu9EhsO2ooieFbtO9PT32EezZw6LZffjKft+xgpH4facAa86wsEgE+lgsHMnEBRUgcRyyLmnT5qB4E5FB-YIU8SYHsh95ofIeZEVK-6egRX5ZiBYELpwuHgVemAfj6SEoUaxwYdyDE4XAeGcGxN6FlKXGkY+XbVDcwnhB2IA0DACAwKg0iiZRCZJHsKzCTB9yfvBhmcbpQmsS+xneohZn6bRYlNrZFmOuxv4SVUbBrAE6lwAICBoLe+4SdhTE5AgLBOCRjGwnAwDjIG4n9CWf4KGOnSajACIsHA0VcNMfloP8ADuLDhMoriwE4KRqBKRZqAUpoOEMhjwH4nj+eMeDhAAkrinQTtk+DiFUnSMaUNABNAKQDTk05FGlnRwIIcXTANzoDWKubjt5rDtItLpvM69l7J0bn9NR5wzJWiwrLRR0mcyzz7aEqHSam74VlcN0ccy93WZmcBxCkC2dLVUq6gqCBPYtmoPsaEOKtD5JeEjcDTOjXwIDQnjQkxexyLh9SNM065nXeL08RQYlvEhfWLWN8DCGeF4COtaBOCwfipCd9PgZB4EKVASkqWp2qaWTcQ80UiQJCDi0APTy4M0gIrImqzvAQYxPwHbjFEshFX58BFbIzUUAEPOdMAbCpAVt4hbCBRFGD-QI0q0xBjIDt5S7wgNQ4+2jdq8Cw2RyQIEVCDAktAgrQN0zq3QDB7YHp2vcaF2TFdX2uJbi01jMdYNhTcMyJLqeYT9AP7UDcv7ej0y5RBq3iKj9cY5sWM48JbeLRSWR5-tPYQDbFJJIkyRqJ5nOiywaiD4HiuxdlgiyH4-kG-Kmox7IY-Tzt2VxXALAQPAZveRUC-7UvWvXjHR-rzQMjjCfsVoGgSdX-nqxeCk3tcv5RAEUCgsg9q6AoX9K4UjznIf2ecl7W0QHAUOj43ZwEjuMMAyhWzAA2LsVOS9Ggf23qvZBlM4DCFUggOAioYBynoLFGAedEEpBQfDehip5oLyXpqDqXBsoQGUmAZScAR4FigDITs5QcobzRjAaI0g2DQFUBg1YMg6IVzYTIaYlCVLOi0RQN2YCJEUFYZTHRVD-apy2qnDKWUyGlxNDzM0AcFZK16kzFgVh4D1AANayGWuMAARiI7qVhVAn3gMQ2QQgipLQgHATg-AeZL1IWgfhqlVbjECDQ1ScoeZ2KgNlJm546Gs0AaeUpl486WRqbeXuZUVBxQoCnVO0504yFaRXEuZF3qek+vMGoX8C7CGmEXMIHSnxfxyMdCui1wpOAXuXQOyzOiHk6LmLaS8ADEuztlwAAKIAA08A8HCAAGQOboBmiAwDAGdNsOJXVurTXEBA65wc4A8CcGg5IJhpgQCCQAK3NjAYGPMWDaxyP8jkFQUgFFRlg1AZRnDQumCwGgIAgkdnhfjd5Nz6gMHWnc1aB9wXI0pHAAABqMSA5QYBUuhvidEOQrAAHEDmhCsNDAxbsiQ-I4QgVaUBohVQgbAhwNyaBgF0bIcOJL+TqXJT-SlwNYoDAJsYXBORYVclgcUaltKID0vlgAEmwLguQjK8RokJHAKw4R-jSi5dDX2fKvkCr1AgXQErdDStlWq2+g1cDavtQARgjWGqw8gsC+3zJC1ErKRgMG5eKMo0BgROByGG8wEql7+tUqYooABaYty9WwIHqHeROwBYZwCCafVmQagEDGob7XQhKwXYBmjgIqNpGCag2E0YAlbBryLoHICVnb4VwCXhWqtWB0mcwCfKRA4gcrgTfqIsAs9K0tuPgkxtHZxE0n1mQ2gtadhAA

#

Ooof, is there a better way to format that link?

#

The consumer side of things seems to be correct at this point, but the Typescript is hideous and clunky.

lone valley
#

If you post the link as a separate message then TS bot will shorten it for you.

mighty summit
#

😔 nitro problems

daring storm
#

I only got nitro so I could post that link....

mighty summit
#

moment

#

it actually works better

#

(or at all)

#

without nitro

#

the bot doesn't work with >2000 char (aka nitro) messages, but it does work with messages sent as text files

mighty summit
daring storm
#

A file, named message.txt, with the link as the contents?

mighty summit
#

yeah

#

without a trailing space and without a trailing newline

daring storm
mighty summit
#

😔