Search code examples
typescriptprogramming-languagesarrow-functions

Why are arrow methods not allowed in Typescript?


The suggestions to allow arrow methods in Typescript have been rejected on the basis on "changing Javascript as language". How would it exactly change the language to have one less character in the function declaration (see add2 and add3 in the example below)?

This is especially confusing to hear considering all other changes Typescript has accumulated compared to Javascript over the years.

export class Point {
    constructor(public x: number, public y: number) {
        this.x = x
        this.y = y
    }

    add1(p: Point): Point {
        return new Point(this.x + p.x, this.y + p.y)
    }

    add2 = (p: Point) => new Point(this.x + p.x, this.y + p.y)

    add3(p: Point) => new Point(this.x + p.x, this.y + p.y)
    
    ...

EDIT

Added links to some of the suggestions


Solution

  • In this answer I am not going to make any value judgments about whether arrow methods would be a good or bad feature, since I don't think that's relevant for the question as asked.


    TypeScript has a set of design goals for the language. One listed goal is to align with current and future ECMAScript proposals, and one listed non-goal is to provide additional runtime functionality.

    Arrow methods are runtime functionality and would be observable at runtime, since presumably writing

    add3(p: Point) => new Point(this.x + p.x, this.y + p.y);
    

    would need to transpile to either

    add3 = (p) => new Point(this.x + p.x, this.y + p.y);
    

    or maybe

    add3(p) { return new Point(this.x + p.x, this.y + p.y); }
    

    so the compiler couldn't merely erase something to get the desired JavaScript output.

    And arrow methods are not set to be introduced to JavaScript. So for these reasons, suggestion to add this to TypeScript would be declined, as you saw in microsoft/TypeScript#18500.


    As you noted, though, such guidelines have not always been followed so strictly. For example, enums are a TypeScript-only feature with runtime effects. And there are parameter properties also.

    But there have been several instances over the years where a TypeScript-only runtime feature conflicted with a similar feature introduced later to JavaScript. Class field declarations were added first to TypeScript and then to JavaScript, and JavaScript implemented different semantics. So now TypeScript had to implement a --useDefineForClassFields compiler option to allow switching between the TypeScript behavior and the expected JavaScript behavior, and thus they have to support both, making the language more complex than it needed to be.

    Similarly, TypeScript introduced decorators before they were mature enough to know what JavaScript was going to do with them, and again, now we have a legacy decorator implementation sitting alongside a new decorator implementation and you need to use a compiler flag to switch between them.

    This is a big headache for the language.

    If JavaScript ever introduces enums or parameter properties, or features similar enough syntactically to conflict, we can expect more headaches. The TypeScript team is quite reluctant now to opt into such headaches without a very strong reason. They generally only want to implement runtime features if those features are upcoming JavaScript features whose semantics are stable enough to be fairly confident that the time and effort won't be wasted. As such a proposed JavaScript feature generally needs to reach Stage 3 of the TC39 process before TypeScript will begin to support it.

    No matter how good a suggestion might be, if it's possible for JavaScript to either implement it or interfere with it, TypeScript will almost certainly turn it down.


    So: if arrow methods are a good idea for TypeScript, they would also be a good idea for JavaScript (except for the type annotations, so it would look like add3(p) => new Point(this.x + p.x, this.y + p.y) at runtime). And therefore interested and committed parties should consider making such a proposal to TC39. If it is adopted, TypeScript would definitely support it.