microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.9k stars 12.47k forks source link

Protected nested classes #10017

Open IceCreamYou opened 8 years ago

IceCreamYou commented 8 years ago

TypeScript Version: 1.8.9

Code

class Outer {
    protected static Inner = class {}
    private myInner: Outer.Inner;
}

Expected behavior: No errors.

Actual behavior: Compiler error: Cannot find namespace 'Outer'. Line 3, Column 24

Code

class Outer {
    protected static Inner = class {}
    private myInner: Outer.Inner;
}
namespace Outer {}

Expected behavior: No errors.

Actual behavior: Compiler error: Module 'Outer' has no exported member 'Inner'. Line 3, Column 32

Code

export class Outer {
    protected static Inner = class {};
}

export class Child extends Outer {
    static temp = class extends Outer.Inner {}
}

Expected behavior: No errors.

Actual behavior: Compiler error: Property 'Inner' is protected and only accessible within class 'Outer' and its subclasses. Line 6, Column 35


The problem here is that there is no way to define a protected nested class in a way that makes it possible to use in a type declaration. The third example shows why I want to use this: I want a nested class that can only be extended by classes that extend the parent class.

RyanCavanaugh commented 8 years ago

This issue is now awaiting more feedback. This means we'd like to hear from more people who would be helped by this feature, understand their use cases, and possibly contrast with other proposals that might solve the problem in a simpler way (or solve many other problems at once).

If this feature looks like a good fit for you, please use the :+1: reaction on the original post. Comments outlining different scenarios that would be benefited from the feature are also welcomed.

e-cloud commented 7 years ago

see one example in webpack

Many existing libraries have already been using class based structure with ES5 syntax. And sometimes they attach another class on a class as a function property. Due to commonjs's exports, this is for namespacing and the nested class can be referenced easily from the consumer code.

If a static member of a class is another class, and the static class can be recognized as a namespace, that would be convenient for some libraries to migrate to Typescript.

RyanCavanaugh commented 7 years ago

Note to self - there's a duplicate of this bug somewhere

michalburger1 commented 6 years ago

The compilation error for the first example now (in Typescript 3) reads:

'Outer' only refers to a type, but is being used as a namespace here.

I'm not sure if there's a better way to do this but I managed to get it to compile using this workaround:

class Outer {
    protected static Inner = class {}
    private myInner: InstanceType<typeof Outer.Inner>;
}
whzx5byb commented 3 years ago

It seems there is a different error in Example 3 in 3.3.3 and later.

export class Outer {
    protected static Inner = class {};
}

export class Child extends Outer {
    static temp = class extends Outer.Inner {}
    //            ~~~~~ '(Anonymous class)' is referenced directly or indirectly in its own base expression.ts(2506)
}

And it is possible to inherite from a public reference to the protected nested class.

export class Outer {
  protected static A1 = class {}

  static A2 = Outer.A1;

  static B1 = class extends Outer.A1 {
    // Error
  }

  static B2 = class extends Outer.A2 {
    // OK, as expected.
  }
}