Condition typescript function handler parameter optionality based on other parameter in the same function

Viewed 36

I have some signature of kind:

export const createNestedTransactions = <T>(
  clients: [DatabasePoolType, DatabasePoolType?],
  handler: (
    outerTransaction: DatabaseTransactionConnectionType,
    innerTransaction?: DatabaseTransactionConnectionType
  ) => Promise<T>
): Promise<T>

My goal here is to provide the possibility for the consumer to provide as many source clients as he wants and I will open nested transactions for those sources. For now, I am playing with max 2 (thus tuple).

I wonder if it is somehow possible to condition that if he will provide both defined sources I could type innerTransaction as required (1) and if only one it will be optional (2):

//1
createNestedTransactions([definedOne, definedTwo], (outer, inner) => {
  assert(outer); // outer not optional
  assert(inner); // inner not optional
}

//2
createNestedTransactions([definedOne], (outer, inner) => {
  assert(outer); // outer not optional
  assert(inner); // inner optional and error
}

And I wonder if I could extrapolate to a tuple of any size?

1 Answers

You are probably looking for something like this:

export const createNestedTransactions = <T extends DatabasePoolType[]>(
  clients: [...T],
  handler: (
    ...args: { [K in keyof T]: DatabaseTransactionConnectionType }
  ) => Promise<T>
): Promise<T> => { return {} as any }

We store the clients in a tuple T. For the arguments of the handler function, we can map over T so we end up with as many arguments as there are clients.

Playground

Related