3

Closed

NoImplicitAny - Compiler and Visual Studio select different overloads - Please see final comment

description

Hi Guys,

Every now and then I turn on the NoImplicitAny compiler switch and try and pick out all the implicit any's I have in my codebase. (Unfortunately I can't have it on the whole time as a good portion of 3rd party typing files also contain implicit any's - but that's another story.)

I just spotted something unusual. It seems that there are occasions where the compiler thinks that a variable is an implicit any but the tooling in Visual Studio 2012 disagrees. While the compiler says:

error TS7012: Parameter 'event' of lambda function implicitly has an 'any' type.

Visual Studio is correctly picking up the type - if you take a look at the enclosed screenshot you can see this in action.

The examples where I have seen this happen have all been using the arrayFilter, arrayFirst, arrayForEach and arrayMap methods which are part of DefinitelyTyped's Knockout typings at present:
    arrayForEach<T>(array: T[], action: (item: T) => void): void;

    arrayForEach(array: any[], action: (any) => void ): void;

    arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;

    arrayFirst(array: any[], predicate: (item) => boolean, predicateOwner?: any): any;

    arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];

    arrayFilter(array: any[], predicate: (item) => boolean): any[];

    arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];

    arrayMap(array: any[], mapping: (item) => any): any[];

As you can see, there are both genericised and non-genericised overloads available. The Visual Studio tooling appears to be selecting the generic overload and the compiler the non-generic overload in each case.

When I experimented with removing the non-generic overloads from Knockout typings I found I was able to get the Visual Studio and the compiler to behave the same way. (And since there was only 1 overload available in each case after my tweaks I guess that makes sense)

This isn't a major issue but I thought I'd flag it up - it would be great if by default both the compiler and Visual Studio behaved the same way when it comes to selecting overloads.

file attachments

Closed Nov 19, 2013 at 6:46 PM by RyanCavanaugh
Looks like this is fixed in 0.9.5. Can you give it a try? https://typescript.codeplex.com/wikipage?title=TypeScript%200.9.5%20beta

comments

danquirk wrote Nov 7, 2013 at 7:44 PM

I can't repro this using the Knockout typings and a few different iterations that look similar to your code. It's entirely possible this issue has been fixed. If you have any specific small repro that you can share we'd be happy to try that again to be sure, just re-open this issue to let us know.

** Closed by danquirk 11/07/2013 12:44PM

johnny_reilly wrote Nov 8, 2013 at 8:52 AM

Hi Dan,

We've removed the non-generic overloads from the published Knockout.d.ts now (they were, as I understand, in place for historic reasons; from before TypeScript had generics). So if testing with the current typings then you wouldn't be able to reproduce the issue.

I've put together a test project that illustrates the problem for you here though. It's just an empty MVC 4 project with the relevant csproj changes for TypeScript compilation.

I've added a historic version of Knockout.d.ts (which itself is riddled with "no implicit any" issues) and a script called error.ts. This should allow you to reproduce the issue I described - look at line 21. Please let me know if it doesn't.

As I say, since we've removed the non-generic overloads from the published Knockout.d.ts this is not an issue causing us any problems. But I thought a situation of Visual Studio and the compiler having different views was probably a symptom of some kind of minor tooling problem which should probably be resolved if possible.

johnny_reilly wrote Nov 8, 2013 at 11:28 AM

I always speak too soon!

In the process of migrating a JavaScript file over to TypeScript I realised that the same (or at least a similar) issue presents when dealing with the jQuery typings.

I enclose a screenshot to illustrate. In the screenshot you can see Visual Studio picking up that event has a type of JQueryEventObject whilst the compiler says it's an implicit any.

Looking at jquery.d.ts I guess it's mixing these 2 overloads up:
submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
submit(handler: (eventObject: JQueryEventObject) => any): JQuery;
For now I can get round this by specifying the type in my function signature. Again, not a massive inconvenience - just something that it would be nice to get fixed at some point...

paulb wrote Nov 8, 2013 at 6:10 PM

This is by design, but the error could be better. The error is actually in the knockout file.

In your demo project change:
arrayForEach(array: any[], action: (any) => void ): void;
to
arrayForEach(array: any[], action: (item: any) => void ): void;
the compiler behaves the same as the language service.

paulb wrote Nov 8, 2013 at 6:10 PM

** Closed by paulb 11/08/2013 11:10AM

johnny_reilly wrote Nov 11, 2013 at 9:59 AM

Thanks @paulb,

Apologies for re-opening but I wasn't sure if you'd spot a comment on a closed issue.

I was just wondering if the explanation you gave for the Knockout typings also covered my experience with the submit handler in the jQuery typings (see previous comment / attached jQueryExample.png screenshot)?

Looking at the submit overloads below it looks like the handler has typings (in the same way that your suggested correction to arrayForEach had typings) but the compiler error remains unless I specify the type in my supplied function signature. Does that sound correct to you?
submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
submit(handler: (eventObject: JQueryEventObject) => any): JQuery;
Again, sorry for re-opening possibly unnecessarily - I just wanted to double-check.

As I say I've been able to resolve this for now by specifying the type in my function signature:
$("form").submit(function (event: JQueryEventObject) {
    // Do some stuff
    // ....
});

paulb wrote Nov 11, 2013 at 5:18 PM

That's a similar problem, we pick the first overload that 'fits', which in this case ends up being:
submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
because "any" fits everything... I agree the error message is unfortunate.

The solution is to reverse the overloads, than it works as expected.

paulb wrote Nov 11, 2013 at 5:19 PM

** Closed by paulb 11/11/2013 10:19AM

johnny_reilly wrote Nov 19, 2013 at 12:53 PM

Hi paulb,

I finally got round to trying your suggestion of reversing the overloads in the jQuery typings file.

I switched jquery.d.ts from this:
submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
submit(handler: (eventObject: JQueryEventObject) => any): JQuery;
To this:
submit(handler: (eventObject: JQueryEventObject) => any): JQuery;
submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
I was expecting that changing the order of the overloads would mean that the compiler picked the first (and the more relevant) overload.

However it's the same situation as before:
  1. Inside the Visual Studio environment the tooling is always picking the more relevant submit(handler: (eventObject: JQueryEventObject) => any) overload (regardless of the ordering in the jquery.d.ts file). The event parameter of my method picks up the type JQueryEventObject flowing through to it without me needing directly specify it; I get intellisense etc inside VS.
  2. The compiler (when I build the solution) reports "Parameter 'event' of lamda function implicitly has an 'any' type." because it is picking the submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any) overload.
Am I missing something? It seems that the compiler and the Visual Studio tooling are still behaving slightly differently...

johnny_reilly wrote Nov 20, 2013 at 1:05 PM

Looks good Ryan - thanks.