Skip to content
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

Design issue - Function typing inconsistency (?) #18749

Closed
bobOnGitHub opened this issue Sep 25, 2017 · 6 comments
Closed

Design issue - Function typing inconsistency (?) #18749

bobOnGitHub opened this issue Sep 25, 2017 · 6 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@bobOnGitHub
Copy link

I tried posting at

<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->

but doesn't look like anyone is reading issues posted over there....

So copy of original post ;

From the Typescript web site ( https://www.typescriptlang.org/docs/handbook/functions.html ) ;

let myAdd: (x: number, y: number) => number =
    function(x: number, y: number): number { return x + y; };

....but an arrow function is not functionally the same as a "function" function - they are not the same (type of) thing ( even if somewhere one is a super class of the other ).

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Sep 25, 2017
@RyanCavanaugh
Copy link
Member

The arrow syntax there is just a shorthand. The only observable differences have to do with this, and you can specify that behavior by writing a this parameter.

@bobOnGitHub
Copy link
Author

Well Ryan, you could work in politics or marketing with the spin you've put on that !! :) - this.... including calls to apply and call and then there're the other differences listed at MDN

I was hoping someone would either

a) advise the documentation was incorrect and provide the correct documentation,
b) explain how it made sense in its current form
or
c) admit it was a shortcoming and advise it was going to be addressed or that, for technical reasons, there was no way to address it.

The arrow syntax has a specific meaning in JS and as TS is a super set of JS the arrow syntax should have the same meaning in TS and not be a shorthand for something else. The syntax given is analogous to having a LanguageX to C++ Transpiler and saying that you can write

int a = 2.6 ;

and the compiler will see 2.6 is a float and replace int withfloat in the output .cpp file - which we all know would be bat$h*& crazy.

@RyanCavanaugh
Copy link
Member

We designed the type syntax ((a: number) => string) and it means exactly we intended it to mean: A callable function of one numeric parameter returning a string. The syntax of the type domain is close to the syntax of the value domain, but they are by no means identical.

You've applied your own interpretation of this syntax ((a: number) => string must mean an arrow function) and assumed it's a bug on our part that our design did not match your assumption.

I can assume that void* x = 0; in C means "Please allocate an int and give me a pointer to it" and then complain that it actually initializes a null pointer, but that's not a bug or oversight in the C language.

@RyanCavanaugh
Copy link
Member

In other words 😉
image

@bobOnGitHub
Copy link
Author

Ok, so the answer to my original question is ;

"The arrow syntax existed in its current form in TS before it was introduced to JS (with its new connotations) <and we are | but we are not> going to change it to mirror the JS standard.

For now, in the context of specifying a type, arrow syntax can be considered as a super type from which the JS arrow function type and JS 'function' function type are independently descended.

There is currently no way to specify a type specific to either type of JS function."

As to applying my own interpretation, the site says "TypeScript starts from the same syntax and semantics that millions of JavaScript developers know today", which syntax and semantics gives my interpretation to the syntax in question. There is no specific mention that some JS syntax has a different meaning in TS specific contexts which is the case here. So, for someone new to TS, my interpretation was at the very least, reasonable.

As to your void* example, of course you would be wrong to 'assume that void* x = 0; in C means "Please allocate an int and give me a pointer to it"' - it means "allocate space to store an address and store the value 0 in it".

This is how a typed variable declaration and assignment is interpreted and implemented which is in keeping with my original interpretation of your syntax ;

let x : () => any = function(x:number){}

being "allocate space for an arrow function and store a "function" function there" which raises the obvious questions unless you are aware of the relevant history and associated peculiarity when the correct interpretation becomes ;

"allocate space for a JS function of any kind and store a "function" function there" which is fine.

What you quite rightly suggest as invalid behaviour is, in the absence of more information, exactly how the syntax appears to be implemented - i.e. It does allocate a "function" function and give you a 'pointer' to it ! - This is what caused me to question it.

I can see a whole lot of confusion and no doubt some subtle this related bug biting someone on the arse at some point.

I presume (as a Humpty fan) that you're paying your arrow syntax extra since ES2015.

@RyanCavanaugh
Copy link
Member

"The arrow syntax existed in its current form in TS before it was introduced to JS (with its new connotations) <and we are | but we are not> going to change it to mirror the JS standard.

No. Arrow functions were in ES Committee at the same time as they were introduced in TypeScript. It is 100%, actually on purpose, for real we thought about it, that the type syntax () => T is interchangeable with non-arrow function expressions.

There is currently no way to specify a type specific to either type of JS function.

It's not clear to me why you would want to, except for the case of this, which you can specify.

There is no specific mention that some JS syntax has a different meaning in TS specific contexts

This cannot possibly be surprising. { x: number } means something different when written in a value position vs a type position, because it has to. You wouldn't look at that and assume well it has to mean exactly the same thing as it would if written as a value, and there's no value named "number", so this must be an error!. The type syntax is clearly its own domain and gets different rules when needed.

On a practical level, rigorously enforcing a distinction between regular and arrow function expressions would be counterproductive. Other than this (which again, you can control for), it would be extremely rare for someone to care which kind of function they were given. Forcing people to explicitly opt in to both kinds of functions at every declaration site would be burdensome for no gain.

I can see a whole lot of confusion and no doubt some subtle this related bug biting someone on the arse at some point.

Which is why we added this parameter types.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

2 participants