Typescript: Add :: operator - as shortcut for Function.bind call

Created on 11 May 2020  ·  15Comments  ·  Source: microsoft/TypeScript

Suggestion

I suggest addition of :: operator.
With behavior similar to Java - e.g. method reference.

Of course, we have function references in TypeScript/JavaScript now.
And functions have bind method, which allows to bind its this to the original object if needed.

This would be just a "syntactic sugar" for convenience .
The resulting JavaScript should stay untouched.

// having object like below:

let someObj = {
  val: 1,
  increment(): number {
    return val++;
  }
};

// You use bind to make context-aware method reference:

const incrObjVal = someObj.increment.bind(someObj);

// this might be equivalent to:

const incrObjVal = someObj::increment;
--------------------------^

Use Cases

  1. Reduce number of bind calls (in fluent API this may have dozens of them line after line)
  2. Reduce number of lambdas created only to wrap class method to make sure this context is maintained.
  3. Prevent from writing some methods as lambdas and some as "methods".
class SomeClass<T> {

  someObj: SomeOtherClass;

  someMethod(array: Array<T>): void {

    array
      .filter(this.lambdaLikeMethod)
      .filter(this.normalMethod.bind(this));
      .map(this.someObj.someFancyMapper.bind(this.someObj))

      // could be replaced with 
      // .filter(this::normalMethod)
      // .map(this.someObj::someFancyMapper);

      // and of course there's no problem to use :: operator on lambda, too
      // .filter(this::lambdaLikeMethod)
      // just as you could call
      // .filter(this.lambdaLikeMethod.bind(this))
      // it's abslutely correct - although not needed overhead

  }

  normalMethod(arg: T): boolean {
    // ..
  }

  // yes you may write it like this and then no use of `bind` is needed
  // but this makes code messy.
  lambdaLikeMethod = (arg: T): boolean => {
    // ..
  }
}

Checklist

My suggestion meets these guidelines:

  • [YES ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [YES] This wouldn't change the runtime behavior of existing JavaScript code
  • [YES] This could be implemented without emitting different JS based on the types of the expressions
  • [YES] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [I HOPE SO ;)] This feature would agree with the rest of TypeScript's Design Goals.
Out of Scope Suggestion

All 15 comments

Wait for tc39 proposal

+1

+1

This is a runtime feature and should be taken up with a TC39 proposal.

This is a runtime feature and should be taken up with a TC39 proposal.

@RyanCavanaugh
I am not sure if we understood properly.
I did not have the intention to add this operator to ECMA Script standard.
I only thought about making tsc understand this operator and transpile it to "bind" call in the resulting JavaScript.

Currently, we don't add new syntax that creates new runtime behavior.

The proposal is already here: https://github.com/tc39/proposal-bind-operator

@RyanCavanaugh

Currently, we don't add new syntax that creates new runtime behavior.

It does NOT create new runtime behavior.
It should be transpiled to JavaScript call which has been valid for a decade.

The proposal is already here: https://github.com/tc39/proposal-bind-operator

Yes, But it's different syntax.

Although the operator and connection to bind method make them similar.

Actually I cannot comment the linked proposal,
and at the moment I do not have time to follow their information on how to get involved (if there any).

So I may only hope that the proposal in that shape will be rejected.

Yes, But it's different syntax.

@moccaplusplus Maybe you should make a tc39 proposal first.

If ts team do something as you told. It will cause conflict with https://github.com/tc39/proposal-bind-operator

@xiaoxiangmoe
I don't know where/how to make tc39 proposal.
But if you know - please feel free to do it - highly appreciated. :)

It does NOT create new runtime behavior.

If you type someObj::increment into your javascript console right now, it produces a syntax error and not a bound form of the function. That's new runtime behavior.

It does NOT create new runtime behavior.

If you type someObj::increment into your javascript console right now, it produces a syntax error and not a bound form of the function. That's new runtime behavior.

@nmain
Analogously, If you type let t: number; into your javascript console right now, it also produces a syntax error.
But it's not a runtime behavior, no f...n way :).

Here it is the same someObj::increment.
The :: should not appear in the transpiled JavaScript.
The typescript compiler tsc should replace it with someObj.increment.bind(someObj)
This is what I meant.

Analogously, If you type let t: number; into your javascript console right now, it also produces a syntax error.

Yes, typescript introduces its own syntax for types. It does not introduce its own syntax for other non-type things. https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals goes into more detail on this.

This is a runtime behavior @moccaplusplus

Because your syntax conflicts with bind-operator. It will cause people who use bind-operator cannot use TS at the same time. Therefore, the TS team will not add this feature.

+1

Was this page helpful?
0 / 5 - 0 ratings