Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instance member function becomes instance member property in mapped types #38496

Open
bajtos opened this issue May 12, 2020 · 2 comments
Open
Labels
Needs Investigation This issue needs a team member to investigate its status.
Milestone

Comments

@bajtos
Copy link

bajtos commented May 12, 2020

TypeScript Version: 4.0.0-dev.20200512

Search Terms:

  • instance member function becomes instance member property
  • mixin property of exported class expression may not be private or protected

Code

export class Application {
  protected getState() {
    return 'starting';
  }

  component(componentCtor: typeof Object) {
    // mount the component
  }
}

// Ideally, I'd like to write `function repositoryMixin(superClass: typeof Application)`, but that
// triggers "property of exported class expression may not be private or protected"
export function repositoryMixin<T extends MixinTarget<Application>>(superClass: T) {
  return class extends superClass {
    component(componentCtor: typeof Object) {
      super.component(componentCtor);
      // register repositories contributed by the component
    }
  }
}

// helpers to work around TypeScript limitations related to mixins

export type Constructor<T extends object> = new (...args: any[]) => T;

export type MixinTarget<T extends object> = Constructor<
  {
    // Enumerate only public members to avoid the following compiler error:
    //   Property '(some-name)' of exported class expression
    //   may not be private or protected. ts(4094)
    [p in keyof T]: T[p];
  }
>;

Expected behavior:

The code compiles cleanly.

Actual behavior:

$  tsc mixin-bug.ts
mixin-bug.ts:13:5 - error TS2425: Class '{ component: (componentCtor: ObjectConstructor) => void; }' defines instance member property 'component', but extended class '(Anonymous class)' defines it as instance member function.

13     component(componentCtor: typeof Object) {
       ~~~~~~~~~

mixin-bug.ts:14:13 - error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.

14       super.component(componentCtor);
               ~~~~~~~~~


Found 2 errors.

Playground Link:

https://www.typescriptlang.org/play/?ts=Nightly#code/MYGwhgzhAECCAO8QEthgC7IPYDtoG8AoaaYLAW3lwFMd0AKMymugYXSwCcAuadAT3jUsAM2gB5AEYArasHQBKAsRLQA9GujksAVzp8AFtVIUqOWuhUBfQjcIi987Hk7UqEZB078AssgAeyDgAPAAq0NT+6LQAJjB+gTihYJwA5tTowQhIqBjOAHz59BA6Qpys4FC8oUpEJK7oOpx4oJAwkdE4cdAlZRVtyqomzOZ0jKYs6OxcvAJCohIycoqDQz2l1JwAdExmFuMjFtOcCgDcKkMa0K6pyBDRnNduWB5eyNQwZHScyJI60TFoJJ+IZjLtJhdoDYSDY7FcjCAyjAONAAO5cADW0BSui60FCgmoAGVgD94OhoChyJ48rgYK5wAC+FgtAEghBCIRIlROBS5sZWHT0JwdPIuGEIlFYjAsEt5PloABeaDmVHQehbTUpVIQXhgHD8ADaAF0lIqFaFzlz-Dy+YToAkgsk0hkJR1pdBZbJ5UroIKcPcRWLOMEVHVVFcAKI4HTkTYYYy4EAg+A6SQoYBaajkSSbZEssAANywyEB6CM0BEWBAICwqKCqWG8GQIE2EU4nBmkKuJAACp2ygJoAByeg4MBxhTDz1iblcJmtKCS+CuKDObuaEjkMAgnBYCm56Ar5CFhOex4r-fLagxLboCD0AAsAAYAJyPhSQw3waBBaAY6h+AWUJjWqb9jXOGFCHyc4gADy+YToAkgsk0hkJR1pdBZbJ5UroIKcPcRWLOMEVHVVFcAKI4HTkTYYYy4EAg+A6SQoYBaajkSSbZEssAANywyEB6CM0BEWBAICwqKCqWG8GQIE2EU4nBmkKuJAACp2ygJoAByeg4MBxhTDz1iblcJmtKCS+CuKDObuaEjkMAgnBYCm56Ar5CFhOex4r-fLagxLboCD0AAsAAYAJyPhSQw3waBBaAY6h+AWUJjWqb9jXOGFCHyc4gA

Related Issues:

@bajtos
Copy link
Author

bajtos commented May 12, 2020

Essentially, I am trying to write a strongly typed class mixin that's exported by a library-like project that's providing .d.ts declarations for consumers.

Ideally, I'd like to implement the mixin function as export function repositoryMixin(superClass: typeof Application), but that's not possible because of #36060/#30355/#17293/#35822/#17744.

As a workaround, I am trying to limit the types seen by the compiler to public members only, using a simple Mapped type. While this workaround works great for mixins that are only adding new members (properties and methods), it does allow mixins to override inherited methods :(

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Jun 5, 2020
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jun 5, 2020
@jcalz
Copy link
Contributor

jcalz commented Oct 7, 2020

duplicate of #27689?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

3 participants