Nicholas Head Nicholas Head - 3 months ago 18
TypeScript Question

Using an import statement breaks other class references?

As a followup to my previous question about using the

bowser
DefinitelyTyped definition file specifically, I implemented the
import
statement as directed by the answer in that question and got further. However now the TypeScript compiler is complaining about code that compiled perfectly fine before all the bowser import nonsense.

Let's say I have MyBowserClass.ts:



import bowser = require('bowser');

namespace MyNamespace {
export class MyBowserClass {
constructor() {
var isIos = (typeof bowser.ios === 'undefined') ? false : bowser.ios;
alert(isIos);

var myInstance = new MyNamespaceTwo.MyOtherClass(); // typescript compiler complains: Property 'MyOtherClass' does not exist on type 'typeof MyNamespaceTwo'.
}
}
}





And then I have MyOtherClass.ts:



namespace MyNamespaceTwo {
export class MyOtherClass {
constructor() {
alert('otherclass ctor');
}
}
}





The compiler is giving me an error here:

var myInstance = new MyNamespaceTwo.MyOtherClass();


saying
Property 'MyOtherClass' does not exist on type 'typeof MyNamespaceTwo'.


So I guess maybe this means I need to also import
MyOtherClass
?

I got this to work by updating my two files:



import bowser = require('bowser');
import otherClass = require('MyOtherClass'); // NEW IMPORT

namespace MyNamespace {
export class MyBowserClass {
constructor() {
var isIos = (typeof bowser.ios === 'undefined') ? false : bowser.ios;
alert(isIos);

var myInstance = new otherClass.MyNamespaceTwo.MyOtherClass(); // changed this to prefix with 'otherClass'
}
}
}







export namespace MyNamespaceTwo { // made this EXPORT
export class MyOtherClass {
constructor() {
alert('otherclass ctor');
}
}
}





This seems like total chaos/craziness. What am I missing here? Why should the
bowser
definition file be a module anyway (when it consists of a global/essentially static method name??) Any guidance/help would be appreciated.

Answer

It seems like you're changing your file from a global declaration file to a module declaration file.

  • a global declaration file makes the types declared in it accessible in your entire project, without the need to import anything. Global declaration files can never import from another file. They also never export, as the types declared in it are available everywhere.

    Eg. a project that uses redux could declare a SpecialAction that can then be used anywhere in the project:

    // index.d.ts
    interface SpecialAction {
      type: string
      isSpecial: boolean
    }
    
    // src/app.ts
    let theAction: SpecialAction = {
      type: 'SPECIAL',
      isSpecial: true
    }
    
  • a module declaration file exports specific types to a module, so the exports can be imported elsewhere in your project. As soon as you import or export in a declaration file, it becomes a module declaration file.

    // index.d.ts
    import { Action } from 'redux'
    export interface SpecialAction extends Action {
      isSpecial: boolean
    }
    
    // src/app.ts
    import { SpecialAction } from '../index'
    let theAction: SpecialAction = {
      type: 'SPECIAL',
      isSpecial: true
    }
    

I hope this helps? ¯\_(ツ)_/¯

Comments