Home > Net >  How to adapt a class to receive different parameters from various functions?
How to adapt a class to receive different parameters from various functions?

Time:03-22

I have a Typescript project in which I am creating a builder to form all the objects of the different methods. I'm trying to adapt the same builder for all methods so as not to clutter the process with classes.

Currently I have two functions with different variables that call the same builder to create each one its object, but since the variables are different I don't know how to pass them to the constructor or how to tell it which variables to take.

This is my current builder class:

export interface Constants {
  sheetId: number,
  lastRow: number,
  totalHeader: number
}
export interface Req {
  requests: Array<object>
}

export class Builder {

  private dataInit: Req;
  private dataProp: Constants;

  constructor(sheetId: number, totalRow?: number, totalHeader?: number) {
    this.dataInit = {
        requests: []
    };
    this.dataProp = {
        sheetId: sheetId,
        lastRow: totalRow ? totalRow : 0,
        totalHeader: totalHeader ? totalHeader : 0
    };               
  }

  testOne() {
    this.dataInit.requests.push(
      {
        dataOne: {
          sheetId: this.dataProp.sheetId,
          endRow: this.dataProp.lastRow
        }
      }
    )
    return this.dataInit;
  }

  testTwo() {
    this.dataInit.requests.push(
      {
        dataTwo: {
          update: {
            sheetId: this.dataProp.sheetId
          },
          change: {
            header: this.dataProp.totalHeader
          }
        }
      }
    )
    return this.dataInit;
  }

}

These are my functions:

function testOneData() {
  let sheet: number = 123;
  let rowTotal: number = 25;

  let dataObj = new Builder(sheet,rowTotal).testOne()

  console.log(JSON.stringify(dataObj))
}

function testTwoData() {
  let sheet: number = 123;
  let headerTotal: number = 2;

  let dataObj = new Builder(sheet,headerTotal).testTwo()

  console.log(JSON.stringify(dataObj))
}

testOneData()

My problem: Right now the first function worked, but the second one returns a 0 in the header key. How can I adapt the builder for both functions or make it generic to implement more functions? How can I know from the builder what variables are coming to me?

CodePudding user response:

If I understand you right, then you want to pass in arguments as a single object rather than a list.

For example:

  constructor({
    sheetId,
    totalRow = 0,
    totalHeader = 0
  }: {
    sheetId: number,
    totalRow?: number,
    totalHeader?: number
  }) {
    this.dataInit = {
        requests: []
    };
    this.dataProp = {
        sheetId,
        lastRow: totalRow,
        totalHeader,
    };               
  }

Now totalRow and totalHeader are referenced by the name of the property on the passed in object, rather than the position on the argument list. And that means you pass them in in any order and omit any optional ones without a problem.

Then you call this constructor like so:

let dataObj = new Builder({sheetId: sheet, totalRow: rowTotal}).testOne()

Or

  let dataObj = new Builder({sheetId: sheet, totalHeader: headerTotal}).testTwo()

And then you get the correct result:

testOneData() // "{"requests":[{"dataOne":{"sheetId":123,"endRow":25}}]}" 
testTwoData() // "{"requests":[{"dataTwo":{"update":{"sheetId":123},"change":{"header":2}}}]}"

See this Typescript Playground for a working example. Just press the "Run" button on the top left to see the console output for yourself.


Just note that if you do this:

new Builder(dataRequiredForTestOne).testTwo() // fine

Then that will be allowed, and it will just use those default zeroes. If that's a problem for your use case then this answer gets more complicated and will require typescript generic parameters, which is probably best answered in another question.

  • Related