Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a backwards compatible way to update a library to use getters?

Tags:

javascript

Assuming a library with a function like:

class Stuff {
  total () {
    return 4; // might be some calculation
  }
}

But you want to update it to use a getter, like:

class Stuff {
  get total () {
    return 4;
  }
}

Is there a way to make a change like this in a backwards compatible way? So code that uses the library assuming a function doesn't break?

stuff.total   // should work with new version
stuff.total() // hopefully this still works

Edit: This question is more about library evolution (more general). The other one is about a particular solution and from a call-site perspective.

like image 611
Alvaro Carrasco Avatar asked Aug 03 '18 16:08

Alvaro Carrasco


1 Answers

You should not do this. stuff.total should either be a number or a function, but not both. That will make for very confusing and difficult to maintain code in the future.

That said, you can do something along the lines of what you want:

class Stuff {
  get total () {
    const callable = function ( ) {
      return 4;
    };
    callable[Symbol.toPrimitive] = callable;
    return callable;
  }
}

const stuff = new Stuff;
console.log( stuff.total );
console.log( stuff.total( ) );
console.log( 1 + stuff.total );
console.log( 1 + stuff.total( ) );

// stuff.total is a function, not a number!
console.log( typeof stuff.total );
console.log( stuff.total.toString( ) );

// But if it's implicitly coerced to a string, it's toString is not called:
console.log( '' + stuff.total);
console.log( `${stuff.total}` );

There are some caveats though. stuff.total is a getter here that is returning a function, not a number. Using that function anywhere a primitive is expected results in the function being called and it's return value being used instead, but it is still really a function. That is evident when you log stuff.total.toString( ) or typeof stuff.total.

like image 95
Paul Avatar answered Nov 12 '22 17:11

Paul