-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Implicit any issue with overloaded methods #11936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I can confirm with Removing the first overload fixes it. Changing the callback to |
Probably caused by #11905 |
this indeed is caused by the change #11905. we should reconsider our fix there. |
This is actually an improvement — Note that
The correct fix is to reverse the order of the overloads or to get rid of the overloads entirely. They are technically redundant but are probably useful as documentation. |
@sandersn Why do you need to fix the type on the first overload? And not just choose the overload that "fits"? In my example, the second overload should clearly be used for 2 argument callbacks. I'm pretty sure though, that previous types where not typed any, at least not on my real world application. I'm also getting the error, when defining a test with Mocha testing framework(this one I'm pretty sure it was not typed as any): it(testName, (done) => { // error 'done' is implicitly typed as any
}) |
@Andy-MS actually fixed jasmine.d.ts this morning to work with the updated compiler. The core limitation, since TypeScript 1.1, is that the compiler will only assign types to any expression once. This gives, unfortunately, extremely subtle semantics. Normally this is fine, but overload resolution changes the contextual type as it tries each overload in order, so you can observe the effect of this limitation. I don't think there's a reasonable way to check overloads besides checking the arguments against each overload in turn. For example, these single-argument functions: declare function f((x: number, y: number, z: number) => string): void;
declare function f((x: string, y: string) => string): void;
f(x => x); Even when there's something that clearly makes an overload unsuitable for an argument, it may be nested deep in the argument or parameter type. So I think it's better to use normal type-checking machinery when possible: just ask whether all arguments are assignable to their respective parameters. In the future, we might go back and rewrite overload resolution but right now we'd prefer to correctly report implicit-any errors from our limited algorithm instead of silently hiding them. |
Thank you for detailed comments. It's really enlightening. I'm thinking about doing overload inference better by choosing overload by their argument length. For example var use: Overload;
use((req: string, res) => {});
interface Overload {
(handler1: (req1: string) => void): void;
(handler2: (req2: number, res2: number) => void): void;
} the argument function will always be contextual inferred against Also, the paramter annotation of string is incompatible with number, it is desirable compiler can detect this and report an error. (theoretically users can inspect function type by inspecting function's source string, Angular1 actually have done this. But that isn't common in JS) |
Well, the top-level overload resolution does check function arity. But in your example, both signatures have arity=1 and the parameters themselves are functions that differ in arity. And this difference in arity could occur at any level, eg class Foo1 {
foo: Bar1;
}
class Foo2 {
foo: Bar2;
}
class Bar1 {
nested(req1: string) => void): void;
}
class Bar2 {
nested(req2: number, res2: number) => void): void;
}
interface Overload {
(handler1: Foo1): void;
(handler2: Foo2): void;
}
let use: Overload
use({
foo: {
nested: (req2, res2) => {
console.log("req2: string, oh no!");
}
}
}) An instance of So I think we need to remove the limitation that once checked, types are fixed, and let type checking operate in a non-permanent fashion. |
@sandersn, why it is not merged to |
@ArtemAvramenko this merging is too permissive in many cases. If the two overload signatures are |
This code was working for me before but broken in the latest:
The text was updated successfully, but these errors were encountered: