Any way to declare a nest class structure in typescript?

Typescript

Typescript Problem Overview


I'm interested in defining an existing framework (openlayers.d.ts) but cannot figure out how to express the fact that OpenLayers.Layer is both a class and a namespace for OpenLayers.Layer.Markers. I believe this makes Markers a nested class of Layer.

usage:

l = new OpenLayers.Layer(...); // this is a base class, never do this
m = new OpenLayers.Layer.Markers(...);

How would you declare both the Layer and Markers class in typescript?

Typescript Solutions


Solution 1 - Typescript

This seems like it has been fixed in versions 0.9.1.1 and later. You just have to create a module with the same name as the class where you want to nest types, and put your nested types in it.

More concretely, this is how you do it:

declare module a
{
    class b
    {
    }

    module b
    {
        class c
        {
        }
    }
}

var myB = new a.b();
var myC = new a.b.c();

This works as well when nesting types in typescript code with the export keyword:

export module a
{
    export class b
    {
    }

    export module b
    {
        export enum c
        {
            C1 = 1,
            C2 = 2,
            C3 = 3,
        }
    }
}

As mentioned by the user @recursive in the comments below, the order of declaration is important. So the class definition must be located before the module with the nested types.

Solution 2 - Typescript

You can use namespace/class merging to get an equivalent effect to nested classes. This example is adapted from Chapter 1 of Pro TypeScript.

You perform merging with a class and a namespace, or with a function and a namespace.

> In all cases, the namespace must appear after the class or function for the merge to work.

Adapted example:

class Outer {
	
}

namespace Outer {
	export class Mid {
		
	}
	
	export module Mid {
		export class Inner {
			
		}
	}
}

var a = new Outer();
var b = new Outer.Mid();
var x = new Outer.Mid.Inner();

Solution 3 - Typescript

As of 2016, I guess this is easier:

class A {
    static B = class { }
}

var a = new A();
var b = new A.B();

Solution 4 - Typescript

Currently there is no support for nested classes.

http://typescript.codeplex.com/workitem/460

Solution 5 - Typescript

This is a bit late but others may find it useful. This is how I did it to fool TS to accomplish the task.

declare module OpenLayers {
  interface Layer { 
   ....
  }

  interface Markers {
    ....
  }
 
  var Layer: {
    new(name:string, options?:any):Layer;
    prototype:Layer;
    Markers: { 
      new(params?:any):Markers;
      prototype: Markers;
    }
  }
}

var markers = new OpenLayers.Layer.Markers();

Solution 6 - Typescript

Use TypeScript's class expressions for this:

var OpenLayers = class {
    static Layer = class {
        static Markers = class {}
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCorey AlixView Question on Stackoverflow
Solution 1 - TypescriptsboisseView Answer on Stackoverflow
Solution 2 - TypescriptFentonView Answer on Stackoverflow
Solution 3 - TypescriptMarcGView Answer on Stackoverflow
Solution 4 - Typescriptuser1793714View Answer on Stackoverflow
Solution 5 - TypescriptLengView Answer on Stackoverflow
Solution 6 - TypescriptVadView Answer on Stackoverflow