-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Make type annotations in function type literals mandatory #3081
Comments
👍 |
it would be interesting to see if this pattern even exists in any of the RWC code bases. i suspect not. |
👍, current behavior was surprising to me when I first encountered it. |
A scan over DefinitelyTyped shows no obvious cases where someone wrote a type name as a variable name. Samples: C:\github\DefinitelyTyped\bootstrap.paginator\bootstrap.paginator.d.ts:
11: itemContainerClass?: (type, page, current) => string;
18: tooltipTitles?: (type, page, current) => string;
22: onPageClicked?: (event, originalEvent, type, page) => void;
23: onPageChanged?: (event, originalEvent, type, page) => void;
24 } C:\github\DefinitelyTyped\durandal\durandal-1.x.d.ts:
15 * Sets the module id on the module.
16 */
17: export var setModuleId: (obj, id: string) => void; C:\github\DefinitelyTyped\fabricjs\fabricjs.d.ts:
18: function parseSVGDocument(doc: SVGElement, callback: (results, options) => void , reviver?: (el, obj) => void ); C:\github\DefinitelyTyped\jquery.contextMenu\jquery.contextMenu.d.ts:
13 delay?: number;
14 determinePosition?: (menu) => void;
15: position?: (opt, x, y) => void;
16 positionSubmenu?: (menu) => void; C:\github\DefinitelyTyped\less\less.d.ts:
533 mime: string;
534 error;
535: push(path: string, callback: (e, root, imported) => void); C:\github\DefinitelyTyped\linq\linq.d.ts:
34 interface Enumerable {
35 //Projection and Filtering Methods
36: CascadeBreadthFirst(func: ($) => any[], resultSelector: (v, i: number) => any): Enumerable; C:\github\DefinitelyTyped\sharepoint\SharePoint.d.ts:
808 getToolTop(): string;
809 getDisabledToolTip(): string;
810: getOnClickCallback(): (event, action: CalloutAction) => any; |
👎 RTFM come on, it's typescript why don't you use types? unless we go pointree functional where parameter names don't mean a thing and signatures like this would mean types rather than names |
Aren't those typeless declarations broken when |
👍 I find this behavior surprising coming from other strongly typed languages, such as C/C++ and Haskell. // C++
// Argument types: string, double
// Return type: Type
Type foo(string, double); -- Haskell
-- Argument types: [Char], Double
-- Return type: Type
foo :: [Char] -> Double -> Type // TypeScript
// Argument types: any, any
// Return type: Type
function foo(string, number): Type; |
And, @spion I agree with that. |
A tslint rule for this is trivial and operates at the syntax level. If
|
TSLint does allow to fix the problem, but it has the downside of disallowing code which is probably okay. I would rather have a static analysis check that the names of the parameters are not also valid types in the scope. So this would be okay shorthand:
but this would be an error:
and also an error:
|
@alexeagle It should be possible to extend TSLint's EDIT: filed a TSLint issue to create a rule which addresses this problem palantir/tslint#723 |
That's because you need On Fri, Oct 9, 2015, 12:58 Alex Eagle [email protected] wrote:
|
@adidahiya that would be a great check to have, I'd turn that on in Angular right away 👍 @IMPinball true, you need those expressions with |
The fact On Fri, Oct 9, 2015, 14:29 Alex Eagle [email protected] wrote:
|
|
@alexeagle The behavior I'm used to expecting from TS is that these three are equivalent types: (number, number) => void
(number: any, number: any) => void
(a: any, b: any) => void |
If you change that behavior, it changes the semantics enough that it would break a lot of existing code. Not everyone uses That significant of a change would be concerning for even a major version increment. |
I think we are talking past each other here. Those are indeed three equivalent types. But the first one is so wrong, I would like a static analysis check to say "you surely, surely did not mean that, and it is clearly a bug". This would not be a language spec change, and in the current landscape, it fits as a tslint check. However, our experience at Google has been that linters are rarely run electively by engineers, and we want these rules consistently applied, so we prefer to plug such rules into the compiler, where everyone is bound by them. |
Ok...I think we can agree to disagree on what we think should be the case. On Tue, Oct 13, 2015, 13:22 Alex Eagle [email protected] wrote:
|
I just don't feel like arguing it any more. On Tue, Oct 13, 2015, 13:28 Isiah Meadows [email protected] wrote:
|
Its very unfortunate that this issue can't be resolved, and I think it should be on the list if / (for whenever) its decided that there will be a breaking release: Just take this type for example: declare function compose<T,U,V>(f1:(u:U) => V, f2: (t:T) => U): (t:T) => V; It could've been written as declare function compose<T,U,V>(U => V, T => U): T => V; which is much more readable. This may not be as important to people already used to the syntax, but it certainly detracts some people away from the language, e.g. https://news.ycombinator.com/item?id=10420940 |
I think it's more of an artifact of basing the function type semantics on the arrow function semantics. If you don't have both, the type of that parameter is implicitly [1] var f: x => number
var f = x => x + 1
var f: (x: any) => number
var f = (x: any) => x + 1 Before ES6, function foo() {
var self = this; // foo's this
return function bar() {
return [
self, // a closure variable
this // bar's this
];
};
}
foo.call(1).call(2); // [1, 2] Or, if s-expressions help make this clearer: (defun foo ()
(let self this) ; foo's this
(defun bar ()
(list
self ; a closure variable
this ; bar's this
))
)
((foo.call 1).call 2) ; [1, 2] And function Construct(Class, args) {
var self = {};
var proto = Class.prototype;
if (typeof proto === "object" && proto !== null) {
self.__proto__ = proto;
}
var res = Class.apply(self, args);
if (res !== undefined) return res;
return self;
} It just tripped up a lot of people. The simplicity is also a reason why I've been slow to adopt the new ES6 object model. I can't stand |
Too many times do we have new users using function type literals without type annotations on their parameters - recently, #3080. Currently the following:
is implicitly typed like:
even though a user probably meant to type
x
like in the following way:It is actually extremely strange that parameter names, which function purely for documentation, are mandatory while their type annotations are optional.
While
--noImplicitAny
catches this, new users often don't know about that flag to begin with.I don't see a good use case for a user who is wiling to type out an arrow type, but wants their parameters to implicitly be typed as
any
. While this is a breaking change, I'm sure most of the breaks would be with code like in the given example.The text was updated successfully, but these errors were encountered: