How can I get a reference an external module in my application declaration file? Please look at following example:
// file meteor.d.ts
declare module "meteor/meteor" {
export module Meteor {
...
}
}
// file context.d.ts
// not part of any module
// not possible to do: import { Meteor } from "meteor/meteor";
declare interface IContext {
Meteor: typeof Meteor; // how do I get the reference to Meteor?
}
Can this even be done?
Can this even be done?
Not at the moment. But I am sure there is an issue here by a TypeScript team member to allow this :rose: < I failed to find it right now though :-/
// not possible to do: import { Meteor } from "meteor/meteor";
Why?
It will remove the ambient context from the file and it will have be explicitly imported in every file. [EDIT] Much better answer by basarat ;)
Why?
If he does import meteor = require('meteor/meteor') then the file becomes a module. He doesn't want that. He wants the file to stay _global_.
you can not "fish" types out of a module and put them in the global space. your only way to get something out of a module, is to import it.
Why do you want to put these typings in the global name space? and why meteor.d.ts does not do that originally? what really happens at runtime? do these exist in the global namespace or not?
Found the issue I was looking for : https://github.com/Microsoft/TypeScript/issues/7125
Quoting a sample library from that issue:
declare var Promise: {
// some stuff here
}
declare module 'bluebird' {
export = Promise;
}
Basically if bluebird was written the way meteor is :
declare module 'bluebird' {
declare var Promise: {
// some stuff here
}
export = Promise;
}
Then it would not be possible to use typeof Promise in a global context if one does indeed do something like : window.Promise = require('bluebird') or something like that.
In the case of meteor is it relevant ... I don't know. I leave that discussion in the hands of @tomitrescak :rose:
But I am sure there is an issue here by a TypeScript team member to allow this
Instead of saying "to allow this" I should have said is "to enable this use case". Because the syntax is different. The issue (again https://github.com/Microsoft/TypeScript/issues/7125) allows the library definition author to enable the library usage in either _global_ or _module_ contexts :rose:
The reason here is to get reference to interfaces from that given module.
For example, module Meteor contains interface Meteor.User. If I want to have in my module a variable of type Meteor.User there is no way for my in the ambient declaration to get reference to it? Does it make sense?
module "meteor/meteor" {
declare module Meteor {
export interface User { ... }
}
}
// my appp
declare interface My {
user: Meteor.User; // impossible
}
[EDIT] This example is almost the same as the one from @basarat
@tomitrescak Why not put My in a file called types.d.ts:
import meteor = require('meteor/meteor');
export interface My {
user: Meteor.User;
}
And import the types wherever you need them:
import {My} from "./path/to/types";
I am similar file here : https://github.com/alm-tools/alm/blob/master/src/common/types.ts :rose:
That is the way I do it now. I was hoping that I will not have to import this interface explicitly as it literally exist in almost every file. I hoped for just declaring it globally and done ;) I had it working before until I encountered external modules.
What I am about to show you is hacky stuff that uses (abuses) the newly introduced declare global (global augmentation) introduced with TypeScript 1.8.
With the :warning: out of the way one can:
globals.d.ts
interface My { // To introduce the name `My` to the global namespace
}
globalsAugment.d.ts
import meteor = require('meteor/meteor');
declare global {
interface My {
user: meteor.User;
}
}
Caveat emptor :rose:
@mhegazy I forgot to say massive THANKS!!!!! That thing is working very nicely and is doing exactly what I need. So once again ... THANKS!!!
@tomitrescak thanks for the kind words. Please let us know if you run into issues.
@basarat Hi, I would like to know if there is already a non-hacky way to achieve this use case.
@basarat Is this still the only way to go? What are the downsides of this hacky method?
Most helpful comment
Workaround
What I am about to show you is hacky stuff that uses (abuses) the newly introduced
declare global(global augmentation) introduced with TypeScript 1.8.With the :warning: out of the way one can:
globals.d.tsglobalsAugment.d.tsCaveat emptor :rose: