Description
TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx)
We have classes defined within a closure that are exposed externally. Closures are required due to angular dependency injection.
While it isn't possible to export the class for instantiation, it would be useful to at least be able to export the declaration of the class for compile time checking. e.g
namespace app {
export function cameraFactory(lensService, buttonService) {
// Export the Camera/Photo class declaration somehow,
// or merge with previous declaration?...
// declare export Camera;
// declare export Photo;
class Photo {
public view() {
alert('photo');
}
}
class Camera {
public takePhoto() : Photo {
lensService.focus();
buttonService.press();
return new Photo();
}
}
class CameraFactory {
public getCamera() {
return new Camera();
}
}
// Note that this function doesn't return a 'Camera', but there is a
// means to obtain one indirectly via other methods and third party frameworks.
return new CameraFactory();
}
// Note the indirect creation of an internal 'Camera' object
// and the requirement to access local 'Camera' class declaration.
// EDIT: modified code to better reflect what is happening -
// the Camera object is being obtained indirectly via a framework.
let camera: Camera = angular.$injector.get('cameraFactory').getCamera();
// let camera: Camera = AltCameraFactory.create();
let photo = camera.takePhoto();
photo.view();
}
We could declare the class separately in a d.ts but that seems redundant and error prone given the class is already being declared.
It could be re-written to do away with the factory and use the injected parameters on the Camera object itself rather than via closure. However there are much more complex factories out there that are dependent on access to closure variables, especially when also taking into account angular injection.
Perhaps it could narrow the type of export that occurs, such that you can simultaneously define the local class implementation and export the class declaration into the namespace for consumption:
namespace app {
export function cameraFactory(lens) {
export declaration class Photo {
public view() { alert('photo'); }
}
}
}
Or it could provide the body for the declaration of a prior empty declaration statement. e.g
namespace app {
export declare class Photo;
export function cameraFactory(lens) {
class Photo declares app.Photo {
public view() { ... }
}
}
}
Another alternative is access to the exported function as it's own namespace and export externally, e.g.
namespace app {
export function cameraFactory(lens) {
class Photo {
public view() { ... }
}
}
export type Photo = cameraFactory.Photo;
}
Or simply allow the exporting of a 'type' from functions:
namespace app {
export function cameraFactory(lens) {
class InternalPhoto {
public view() { ... }
}
export type Photo = InternalPhoto;
}
}
Or if you "export" a local class from a function, all that occurs is the type declaration is made visible at compile time and it cannot be instantiated.
Expected behavior:
An ability to export at least the declaration of the 'Camera' and 'Photo' class so it can be used for type checking and code completion externally.
Actual behavior:
"Modifiers cannot appear here" error when trying to export.
The inability to reference the 'Camera' or 'Photo' classes externally for compile time checking.