Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript :: namespacing functions within a class?

Tags:

typescript

Assume a simple class like so:

class Simple {
  private _transactions: [];
  makeTransaction() { ... }
  revertTransaction() { ... }
  // some other methods as well...
}

let obj = new Simple();
obj.makeTransaction(...);
obj.makeTransaction(...);
obj.revertTransaction(...);

Now, I want to expose some more methods related to reporting and I would like to group them like so:

obj.reports.allTransactions();
obj.reports.reveretedTransactions();
obj.reports.clearedTransactions();

These methods will be using the private variables within the Simple class itself to return some reports.

I have used the following to achieve this:

class Simple {
  private _test = () => { return this._transaction }
  reports = {
    getAll: this._test
  }
}

This works, but it has a couple of downsides:

  1. It forces me to declare all required functions as part of the class itself and then reference them in the reports object again.
  2. Typescript shows me that obj.reports.getAll is a property, although I can invoke it as a function too. Even so, I don't get the correct function signature hint.
  3. It forces me to use arrow functions (closures) needlessly.

Is there a better way of doing the same?

like image 397
AweSIM Avatar asked Jul 05 '26 20:07

AweSIM


1 Answers

You can create a class for the reports object:

class Reports {
    private _transactions: any[];

    constructor(transactions: any[]) {
        this._transactions = transactions;
    }

    getAll() {
        return this._transactions;
    }
}

class Simple {
    private _transactions: any[];
    public reports: Reports;

    constructor() {
        this._transactions = [];
        this.reports = new Reports(this._transactions);
    }

    makeTransaction() {}
    revertTransaction() { }
}

(code in playground)


Edit

You can also expose reports as a type:

interface Reports {
    getAll(): any[];
}

class Simple {
    private _transactions: any[];
    public reports: Reports;

    constructor() {
        this._transactions = [];
        this.reports = {
            getAll: () => {
                return this._transactions;
            }
        }
    }

    makeTransaction() {}
    revertTransaction() { }
}

(code in playground)


2nd Edit

Another option is to seperate the reports into a different class but to have the Simple instance as its member with all members of the instance as public.
If you then turn Simple into an interface you can hide those public members:

class Reports {
    private _simple: SimpleImpl;

    constructor(simple: SimpleImpl) {
        this._simple = simple;
    }

    getAll() {
        return this._simple.transactions;
    }
}

interface Simple {
    makeTransaction();
    revertTransaction();
}

class SimpleImpl implements Simple {
    public transactions: any[];
    public reports: Reports;

    constructor() {
        this.transactions = [];
        this.reports = new Reports(this);
    }

    makeTransaction() {}
    revertTransaction() {}
}

(code in playground)

If only Reports class and the Simple interface are exposed then the public members are only visible to the instances of Reports.

like image 129
Nitzan Tomer Avatar answered Jul 07 '26 11:07

Nitzan Tomer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!