Skip to content

Private name "#..." must be declared in an enclosing class when referencing from decorator #3394

Closed
@akcyp

Description

esbuild version: 0.19.3

Context: Private class fields should be only available from inside of class declaration. We can move accessor to outside context but still we have to declare it "inside" class declaration, like in this example:

let x
class A {
    #test = 42;
    static {
        x = (obj) => obj.#test;
    }
}
console.log(x(new A)); // 42
// Works correctly in both typescript and esbuild compiler

The problem: When using decorators syntax we cannot reffer to private fields. Example:

type AttributeOptions<T> = {
  onChange?: (this: T, value: string, oldValue: string) => void;
};

const Attribute = <T, V>(options: AttributeOptions<T> = {}) => (
  value: ClassAccessorDecoratorTarget<T, V>,
  _: ClassAccessorDecoratorContext<T, V>,
): ClassAccessorDecoratorResult<T, V> => {
  const { get, set } = value;
  return {
    get() {
      return get.call(this);
    },
    set(value) {
      const oldValue = get.call(this);
      set.call(this, value);
      options.onChange?.call(this, value as string, oldValue as string);
    },
  };
};

class CustomHTMLElement {
  #test = 'test';
  @Attribute({
    onChange() {
      console.log(this.#test); // <- fails on esbuld
    }
  }) accessor field = '';
}

new CustomHTMLElement().field = '';

Typescript working example: Playground Link

Esbuild not working example: Playground Link

image

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions