I'd like to tell the type checker that such and such tuples must each consist of a function and valid arguments, e.g.
let expressions:TYPE[] = [
[(a:number, b:string)=>{},1,"ok"], // ok
[(a:number)=>{},true] // error
[(a:number)=>{}] // error
[(a:number, b:string)=>{},1] // error
]
The current solution I have uses a function. It gets redundant:
expression<F extends (...args:any[])=>any>(fn:F, ...params:Parameters<F>){
return [fn,...params]
}
let queue:ReturnType<expression>[] = [
expression(...),
expression(...),
expression(...),// seriously?
]
It might be tolerable if I could do it in one call, e.g.
let queue = expressions(
[(a:number)=>{},1], // ok
[(a:number)=>{},true] // error
[(a:number)=>{}] // error
)
But writing that function is beyond me. It seems to require a generic tuple type I don't think is possible and that landed me with the expression function call in the first place.
Here's a naive tuple type that doesn't work / requires gross overhead.
type Expression<F extends (...args:any[])=>any = (...args:any[])=>any> = [F,...Parameters<F>]
let queue:Expression[] = [
[(a:number)=>{},true] // No error
]
// Gross alternative:
const fn = (a:number)=>{}
queue = [
[fn,true] as Expression<fn> // Error as desired, but c'mon.
]