Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Last active March 30, 2023 13:12
Show Gist options
  • Save karol-majewski/dc979192186df66c1580a569c194e53a to your computer and use it in GitHub Desktop.
Save karol-majewski/dc979192186df66c1580a569c194e53a to your computer and use it in GitHub Desktop.
Decorator that binds class methods compatible with TypeScript 5.0
function bound<This extends object, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
const methodName = String(context.name);
if (context.private) {
throw new Error(`${bound.name} cannot decorate private properties like ${methodName}.`);
}
context.addInitializer(function () {
Object.assign(this, { [methodName]: target.bind(this)})
});
}
@karol-majewski
Copy link
Author

karol-majewski commented Mar 30, 2023

Example:

class Rolodex<const T> {
  index: number;
  length: number;

  constructor(private sequence: NonEmptyArray<T>) {
    this.sequence = sequence;
    this.index = 0;
    this.length = sequence.length;
  }

  @bound
  next(): T {
    return this.sequence[++this.index % this.length]!;
  }
}

const { next } = new Rolodex([10, 20, 30]);

console.log(next()) // without the decorator, it would throw "Cannot read properties of undefined (reading 'sequence')"

TypeScript Playground
Official documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment