TypeScript closure is an "almost" solution

One of my biggest mistakes with TypeScript is that it compiles all methods (regardless of the access modifier) ​​to the prototype.

Example

class Example {
    public getString(): string {
        return "Hello World";
    }

    private getNumber(): number {
        return 123;
    }
}

      

As you know, access modifiers are only checked at compile time, so they are ignored by emitted JavaScript. One of the ways JavaScript developers have learned to mitigate this is by using closures (well, we know there are performance penalties that pay with closures, but I believe there are cases where closures are absolutely necessary).

Example

var Example = (function () {
    function Example() {
        this.getString = function () {
            return "Hello World";
        }

        var getNumber = function() {
            return 123;
        }
    }

    return Example;
})();

      

The example above is for public / private access.

I designed this using lambda syntax, we can declare public closure methods in TypeScript.

Example

class Example {
    getString = (): string => {
        return "Hello World";
    }
}

      

It's not particularly pretty, but it works.

I would like to know the following: How do I declare private closures in TypeScript?

Example

class Example {

    // TypeScript doesn't like this!
    var getNumber = (): number => {
        return 123;
    }
}

      

More on this bugbear here: https://github.com/Microsoft/TypeScript/issues/2940

+3


source to share


2 answers


TypeScript casts types and accessors to ES6 (and it checks statically). The class

TypeScript class

keyword is a standard ES6 keyword. There are no private closures in ES6 classes. This syntax is not valid in ES6:

class Example {
    var v = /* ... */; // invalid in ES6
}

      

If you need to declare a closure that encapsulates variables, you must use the classic JavaScript way. I highly recommend using TS interfaces:

interface NamedObject {
    getName(): string;
}

let createNamedObject = function (name = 'John'): NamedObject {
    return {
        getName: function () {
            return name;
        }
    };
};

let obj: NamedObject = createNamedObject();

      




If you really want to create class methods with closures, you can do this:

class BadPerformance {
    public getName: () => string;

    constructor(name = 'John') {
        this.getName = () => {
            return name;
        };
    }
}

      

+6


source


As you know, access modifiers are only checked at compile time, so they are ignored by emitted JavaScript.

This is because privacy in this context is the privacy of an API from another developer. If you want them to know that a method is confidential, provide a file .d.ts

so their editor can know it or not document it in the API documentation.

In JavaScript, documentation is often viewed as an API.



I would like to know: How do I declare a closure in TypeScript?

You can create functions in the constructor that declare them on the instance, not on the prototype. This will allow you to use closures - it also goes against the prototypical inheritance and nature of TypeScript and JavaScript.

+1


source







All Articles