Reputation: 685
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.
]
Upvotes: 1
Views: 76
Reputation: 23885
The solution to this problem looks like this:
function expressions<
F extends any[]
>(...functions: [...{
[K in keyof F]: [
(...arg: F[K]) => any,
...F[K]
]
}]
){
return functions
}
We use the generic type F
to store the the types of the arguments of the passed functions in a tuple. The type of each function will be stored in F[K]
which we will also use to type the second element in the tuple.
Let's see if it works:
let queue = expressions(
[ (a:number, b: string) => {}, 1, "abc"],
[ (a:boolean) => {}, true],
[ (a: Date) => {}, new Date()],
[ (a: number) => {}, false] // Error: Type 'boolean' is not assignable to type 'number'
)
let queue2 = expressions(
[ (a: number) => {} ] // Error: 'unknown' is not assignable to type 'number'
)
Upvotes: 2