1

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][]){
   ...
}

2 Answers 2

1

Playground
But srsly consider some other structure

import { F } from "ts-toolbelt"

// [T1] or [T1, T2, T1] or [T1, T2, T1, T2, T1]
type ToOddEvenOdd<A extends any[], T1, T2, P extends any[]> =
    | A extends [] ? [...P, T1]
    : A extends [infer F extends T1] ? [...P, F]
    : A extends [infer F extends T1, infer S extends T2, ...infer L] ? ToOddEvenOdd<L, T1, T2, [...P, F, S]>
    : A extends [infer F, infer S, ...infer L] ? ToOddEvenOdd<L, T1, T2, [...P, T1, T2]>
    : [[A]]


type ODD = () => boolean
type EVEN = 'and' | 'or' | 'then'
function g<A extends any[]>(
    ...args:
        A extends ToOddEvenOdd<A, ODD, EVEN, []> ? A
        : 
        F.NoInfer< ToOddEvenOdd<A, ODD, EVEN, []> >
) { }

g(() => true)
g(() => true, 'and', () => false)
g(() => true, () => false)
g(() => true, 'and')
g(() => true, () => false, () => false)
g(() => true, 'and', 'and')
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.