Function binding in TS

I have written a pretty decently sized project and have noticed that i cannot write functions like such maybe i am doing something wrong? Does anyone know of this?

How i want to write it:

export AClass {
    function aMethod(): string {
         return "test";
   }
}

How im being forced to write:

export AClass {
    constructor() {
         this.aMethod = aMethod.bind(this);
    }
    aMethod = function() {
         return "test";
    }
}

Hello @JayArrowz, since the examples are not ES5 JS, could you please share the transpiled index.js code and clarify what issue you encounter with the first example?

Yes, thank you here are some more details:

Take for example my Mob.ts class has this inside it:

    getIsActive(): boolean {
        return this.isActive;
    }

It transpiles down to this (disregard other code and take a look at getIsActive):

var Mob = (function (_super) {
    __extends$3(Mob, _super);
    function Mob(position, entityType, state, energy, worldIndex, walkingQueue, worldOwner) {
        var _this = _super.call(this, worldIndex, state, position, entityType, worldOwner) || this;
        _this.lastDirection = Direction$1.None;
        _this.firstDirection = Direction$1.None;
        _this.secondDirection = Direction$1.None;
        _this.setActive = function (active) {
            this.isActive = active;
        }.bind(_this);
        _this.getDirections = function () {
            if (this.firstDirection !== Direction$1.None) {
                return this.secondDirection === Direction$1.None ? [this.firstDirection] : [this.firstDirection, this.secondDirection];
            }
            return Direction$1.emptyDirectionArray;
        }.bind(_this);
        _this.energy = energy;
        _this.walkingQueue = walkingQueue;
        _this.blockSet = new SynchronizationBlockSet();
        _this.walkingQueue = walkingQueue;
        _this.isActive = true;
        return _this;
    }
    Mob.prototype.getIsActive = function () {
        return this.isActive;
    };
    return Mob;
}(Entity));

Now if my server calls this getIsActive:
game-server-nakama-1 | {"level":"warn","ts":"2022-07-21T15:45:51.921Z","caller":"server/match_handler.go:295","msg":"Stopping match after error from match_loop execution","mid":"c7d1e01c-dda9-468d-8a01-2fdb78dc7007","tick":267,"error":"TypeError: Object has no member 'getIsActive' at matchLoop (index.js:10348:31(23))"}
here is the line it is erroring on 10348:

Instead i’m have to write the function like this so it works (AND the second way also works with the bind being inside the constructor this.getIsActive = this.getIsActive.bind(this)):

    getIsActive = function(): boolean {
        return this.isActive;
    }.bind(this);

More info:
Here is my index.ts:

export * from "./modules/rpc/WorldRpc"
export * from "./modules/match/WorldMatch"

Here is my rollup config:

import resolve, { nodeResolve } from '@rollup/plugin-node-resolve';
import commonJS from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import typescript from '@rollup/plugin-typescript';
import pkg from './package.json';
import multiInput from 'rollup-plugin-multi-input';
import nodePolyfills from 'rollup-plugin-node-polyfills';

const extensions = ['.mjs', '.js', '.ts', '.json'];

export default {
    input: "./src/index.ts",
    external: ['nakama-runtime'],
    plugins: [
        // Allows node_modules resolution
        
        nodeResolve({ extensions, browser: true }),
        nodePolyfills(),
        resolve({ extensions }),
        // Compile TypeScript
        typescript({
            noImplicitReturns: true,
            moduleResolution: "node",
            experimentalDecorators: true,
            esModuleInterop: true,
            noUnusedLocals: false,
            noUnusedParameters: false,
            removeComments: true,
            target: "es5",
            module: "ESNext",
            strict: false,
            downlevelIteration: true
        }),

        json(),

        // Resolve CommonJS modules
        commonJS({ extensions }),
        
    ],
    output: {
        dir: 'build',
    },
};

It would be great if you could provide a complete, simple example with all the necessary rollup setup that I can easily transpile locally to reproduce the issue, please.

Will provide a github repo on the weekend to reproduce issue :smiley:

1 Like

You can’t store classes inside state unfortunately

@formatCvt damn :S im hoping this is not the case, cause most of my state is objects such as Player class etc… I never saw this in any doc either

@sesposito here is my issue on this repo:
[JayArrowz/NakamaTypescript: Nakama TS (github.com)] (GitHub - JayArrowz/NakamaTypescript: Nakama TS)

Please run npm install first.
You can use npm run run to run the docker container or npm run build to transpile

You’ll notice the error inside the match loop when you reference myClass.getInteger().

{"level":"warn","ts":"2022-07-23T23:57:11.138Z","caller":"server/match_handler.go:295","msg":"Stopping match after error from match_loop execution","mid":"4f29f600-e232-48ef-8fa8-87865feb062f","tick":0,"error":"TypeError: Object has no member 'getInteger' at matchLoop (index.js:61:54(9))"}

Now if i use this implementation of MyClass it works:

Hi @JayArrowz I am also facing this issue. I want to maintain a class variable in game state belonging to a third-party npm module. Could you find a proper solution for using class variable in the game state?