question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow accessors to support inline generics for this

See original GitHub issue

Search Terms

getter, accessor, this, generic

Suggestion

Currently accessor declarations do not support generics at the declaration site. The error returned is An accessor cannot have type parameters.ts(1094). Currently the accessor can implement generic declaration via the enclosing class. The goal would be to allow for the accessor to support a generic this at the declaration site.

Use Cases

The use case is to allow for more expressive setter/getter declarations, in line with how method declarations currently work.

Examples

Suggested Pattern

Below is an example of defining the constraints of this at the accessor site, to determine if an inherited accessor method is valid by the shape of the subclass.

class Base {
   get left<T extends { _left: string}>(this: T) {
       return this._left;
   } 
   get right<T extends { _right: string}>(this: T) {
       return this._right;
   } 
}

...
class Left extends Base {
    _left: string = '';
}
new Left().left; // OK
new Left().right;  // Errors

...
class Right extends Base {
   _right: string = '';
}
new Right().right; // OK
new Right().left; // Errors

...
class Both extends Base {
   _right: string = '';
   _left: string = '';
}
new Both().right; // OK
new Both().left; // OK

This pattern can currently be emulated by converting the accessors into standard methods

class Base {
  getLeft<T extends { _left: string}>(this: T) {
      return this._left;
  } 
  getRight<T extends { _right: string}>(this: T) {
      return this._right;
  } 
}

...
class Left extends Base {
   _left: string = '';
}
new Left().getLeft(); // OK
new Left().getRight(); // Errors

...
class Right extends Base {
  _right: string = '';
}
new Right().getRight(); // OK
new Right().getLeft(); // Errors

...
class Both extends Base {
  _right: string = '';
  _left: string = '';
}
new Both().getRight(); // OK
new Both().getLeft(); // OK

Checklist

My suggestion meets these guidelines:

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

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:36
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
twbjecommented, Jan 20, 2020

I would love that feature, too. I would like to use getters for “modifiers” without arguments, that return a modified object of the same type. E.g.:

class A {
  protected val: string;
  public withString<T extends A>(this: T, val: string): T {
    this.val = val;
    return this;
  }

  public get And<T extends A>(this: T): T {
    return this;
  }

  public get inUpperCase<T extends A>(this: T): T {
    this.val = this.val.toUpperCase();
    return this;
  }

  public toString(): string {
    return this.val;
  }
}

const a = new A().withString("test").And.InUpperCase;

console.out(a.toString()); // TEST

In this particular case, we could return type A, but as soon as we start with inheritance:

class B extends A {
}

const b = new B().toUpperCase;

the type of b would be converted to A.

2reactions
JohnLouderbackcommented, Jan 10, 2021

I agree with the need for this. The use case I ran in to today required me to change my getter to a method, which is annoying as it’s inconsistent with the rest of my code and I’m only doing it to support the type parameters.

  public getAllSettings<T extends this>(): Array<Setting<T>> {
    return (allPropertiesOf(this) as Array<keyof T>)
      .filter(prop => Reflect.getMetadata('setting', this, prop as string))
      .map(prop => {
        const metadata = Reflect.getMetadata('setting', this, prop as string);
        return {
          name: metadata.name,
          controlType: metadata.controlType,
          value: new Ref(this as T, prop)
        };
      });
  }

I need this because my method is defined in an abstract parent class. If I simply use keyof this it only allows for keys in the parent class and not the subclasses that inherent from it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Defining a type-safe generic object accessor function in ...
The problem in the way you define getter is that Typescript does not support partial argument inference. So when you say getter<Book> the ......
Read more >
Inline Functions - Kotlin - W3cubDocs
The inline modifier can be used on accessors of properties that don't have a backing field. You can annotate individual property accessors: val...
Read more >
typescript-cheatsheet - GitHub Pages
A set of TypeScript related notes used for quick reference. The cheatsheet contains references to types, classes, decorators, and many other TypeScript ...
Read more >
Generic Subscripts - Discussion - Swift Forums
Not just syntax stuff, either - they also don't support @inline(__always) for some ... Before I submit it, could someone let me know...
Read more >
Documentation - Decorators - TypeScript
To enable experimental support for decorators, you must enable the ... Parameter Decorators, followed by Method, Accessor, or Property Decorators are ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found