typescriptspread-syntaxfunction-parameterconditional-types

How to restrict function parameters types base on if the index of parameter is even or odd in typescript?


What I'm looking for is to have a function with infinite number of parameters and each parameter type is based on if its index is even or odd.

A contrived example:

flow(isMachineReady(), 'and', isWaterHot(), 'or', isMilkHot(), 'then', serveCoffee())

Odd arguments: () => boolean Even arguments: 'and' | 'or' | 'then'

So if the function was used like this I want to get error for the second argument type:

flow(isMachineReady(), **isWaterHot()**, 'or', isMilkHot(), 'then', serveCoffee())

Here is what I tried before but didn't work

type FlowArgCouple = [operand: () => boolean, operator: 'and' | 'or' | 'then']

function flow(...args: [...FlowArgCouple][]){
   ...
}

Solution

  • Nice one Dimava, the solution you have works. Although for some reason it takes time for typescript to find out the error.

    I find out another solution which also works well. But same issue, not always gives you the error as soon as it's there. But I add this answer as well, in case anyone else running to the same question can use it:

    Playgournd

    type Operand = () => boolean
    type Operator = 'and' | 'or' | 'then'
    
    type ValidRepeatedTuple<
        T extends readonly unknown[],
        U extends readonly unknown[]
    > = U extends readonly []
        ? U
        : readonly [...T, ...(U extends readonly [...T, ...infer R] ? ValidRepeatedTuple<T, R> : [])]
    
    type FlowArgs<U extends readonly unknown[]> = [
        ...ValidRepeatedTuple<[Operand, Operator], U>,
        Operand
    ]
    
    function flow<U extends unknown[]>(...args: FlowArgs<U>){
    }
    
    flow(() => true)
    flow(() => true, 'and', () => false)
    flow(() => true, () => false)
    flow(() => true, 'and')
    flow(() => true, () => false, () => false)
    flow(() => true, 'and', 'and')