Reputation: 6814
Given these types below, I am not sure why the inferred type of executor.get()
is different depending on how I invoke console.log
.
I've included a link to the TypeScript playground for your convenience.
interface Stage<T, R> {
consume(element: T): void;
}
function peek<T>(action: (element: T) => void): Stage<T, T> {
return {
consume(element: T) {
action(element);
}
};
}
class Executor<T> {
run<A>(stage1: Stage<T, A>): Executor<A>;
run<A, B>(stage1: Stage<T, A>, stage2: Stage<A, B>): Executor<B>;
run(...stages: Stage<any, any>[]): Executor<any> {
return this;
}
get(): T {
return null as T;
}
}
If I do peek(element => console.log(element))
, then the inferred return type of get()
is number
which is correct.
const executor = new Executor<number>();
executor.run(
peek(element => console.log(element))
).get();
But if I do peek(console.log)
like below, then the inferred return type of get()
is any
which I don't understand why. I think because the signature of console.log
is console.log(...data: any[]): void
, so when I just pass a reference to console.log
like below, TypeScript infers that the type of element
is any
, but I want number
, what should I do to make TypeScript infer the correct type?
const executor = new Executor<number>();
executor.run(
peek(console.log)
).get();
Upvotes: 0
Views: 268
Reputation: 627
console.log
has the following type log(message?: any, ...optionalParams: any[]): void;
. As such peek
when called upon console.log
will infer that T
is of type any
(which is the type of the first argument of console.log).
To fix this, you need to manually tell peek that you will be expecting a number:
const executor = new Executor<number>();
executor.run(
peek<number>(console.log)
).get();
Upvotes: 2