Home > database >  Do I have to convert a JavaScript module to a TypeScript class to keep using 'this'?
Do I have to convert a JavaScript module to a TypeScript class to keep using 'this'?

Time:11-26

I'm in the process of converting a JavaScript project to Typescript.
I have an old module file that was require()-d from the main.js file of the project.

Here is the simplified example:

//required_module.js

const foo = require("bar");

module.exports = {
    start(myvar) {
        this.myvar = myvar;
        this.myfunc('str1');
        this.myfunc('str2');
    },
    myfunc(type) {
        const other = new foo.stuff;

        if (type === 'str1') {
            other.fn1(this.xbar(type));
        }
        else if (type === 'str2') {
            other.fn2('blahblah', this.xbar(type));
        }

        other.go();
    },
    xbar(type) {
        return this.myvar.asd(type);
    }
};

As you can see, this is just a simple JS module file (not a class), that uses this many times, and it just works as expected.

However as I try to convert this module to a TypeScript module without creating a class from it, I get different kind of errors at the this references as I try different approaches, like:

Object is possibly 'undefined'.ts(2532)
'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)
An outer value of 'this' is shadowed by this container.

Is the only solution to create a class or TypeScript also allows using this outside of classes in a specific way?

CodePudding user response:

Based on the helpful comments, the answer is:

You probably don't have to convert it to a class, but you'd be better off: you are going to run into issues dynamically adding properties (like myvar) or calling methods on untyped objects. Typescript doesn't want you treating JS objects as a random grab-bag of properties: there's already another data structure for that
- Jared Smith

I'd focus less on converting to typescript and more on converting to modern module syntax. If you used named exports instead of object methods, you wouldn't have these issues. You would however have a stateful, static, module-scoped myvar variable (as you currently do), which should be avoided. Instead of the singleton, a class that can be instantiated multiple times might be the better approach.
- Alex Wayne

The example, simply converted code would look like something like this in TypeScript:

import foo from 'bar';

export default {
    myvar: 0,

    start(myvar: number) {
        this.myvar = myvar;
        this.myfunc('str1');
        this.myfunc('str2');
    },

    myfunc(type: 'str1' | 'str2') {
        const other = new foo.stuff;

        if (type === 'str1') {
            other.fn1(this.xbar(type));
        }
        else if (type === 'str2') {
            other.fn2('blahblah', this.xbar(type));
        }

        other.go();
    },

    xbar(type: string) {
        //...
    }
};
  • Related