How do I use namespaces with TypeScript external modules?

前端 未结 9 1300
陌清茗
陌清茗 2020-11-22 08:59

I have some code:

baseTypes.ts

export namespace Living.Things {
  export class Animal {
    move() { /* ... */ }
  }
  export class          


        
相关标签:
9条回答
  • 2020-11-22 09:24

    Several of the questions/comments I've seen around this subject sound to me as if the person is using Namespace where they mean 'module alias'. As Ryan Cavanaugh mentioned in one of his comments you can have a 'Wrapper' module re-export several modules.

    If you really want to import it all from the same module name/alias, combine a wrapper module with a paths mapping in your tsconfig.json.

    Example:

    ./path/to/CompanyName.Products/Foo.ts

    export class Foo {
        ...
    }
    


    ./path/to/CompanyName.Products/Bar.ts

    export class Bar {
        ...
    }
    


    ./path/to/CompanyName.Products/index.ts

    export { Foo } from './Foo';
    export { Bar } from './Bar';
    



    tsconfig.json

    {
        "compilerOptions": {
            ...
            paths: {
                ...
                "CompanyName.Products": ["./path/to/CompanyName.Products/index"],
                ...
            }
            ...
        }
        ...
    }
    



    main.ts

    import { Foo, Bar } from 'CompanyName.Products'
    

    Note: The module resolution in the output .js files will need to be handled somehow, such as with this https://github.com/tleunen/babel-plugin-module-resolver

    Example .babelrc to handle the alias resolution:

    {
        "plugins": [
            [ "module-resolver", {
                "cwd": "babelrc",
                "alias": {
                    "CompanyName.Products": "./path/to/typescript/build/output/CompanyName.Products/index.js"
                }
            }],
            ... other plugins ...
        ]
    }
    
    0 讨论(0)
  • 2020-11-22 09:30

    The proper way to organize your code is to use separate directories in place of namespaces. Each class will be in it's own file, in it's respective namespace folder. index.ts will only re-export each file; no actual code should be in the index.ts file. Organizing your code like this makes it far easier to navigate, and is self-documenting based on directory structure.

    // index.ts
    import * as greeter from './greeter';
    import * as somethingElse from './somethingElse';
    
    export {greeter, somethingElse};
    
    // greeter/index.ts
    export * from './greetings.js';
    ...
    
    // greeter/greetings.ts
    export const helloWorld = "Hello World";
    

    You would then use it as such:

    import { greeter } from 'your-package'; //Import it like normal, be it from an NPM module or from a directory.
    // You can also use the following syntax, if you prefer:
    import * as package from 'your-package';
    
    console.log(greeter.helloWorld);
    
    0 讨论(0)
  • 2020-11-22 09:31

    dog.ts

    import b = require('./baseTypes');
    
    export module Living.Things {
        // Error, can't find name 'Animal', ??
        // Solved: can find, if properly referenced; exporting modules is useless, anyhow
        export class Dog extends b.Living.Things.Animal {
            public woof(): void {
                return;
            }
        }
    }
    

    tree.ts

    // Error, can't use the same name twice, ??
    // Solved: cannot declare let or const variable twice in same scope either: just use a different name
    import b = require('./baseTypes');
    import d = require('./dog');
    
    module Living.Things {
        // Why do I have to write b.Living.Things.Plant instead of b.Plant??
        class Tree extends b.Living.Things.Plant {
        }
    }
    
    0 讨论(0)
  • 2020-11-22 09:35

    Try this namespaces module

    namespaceModuleFile.ts

    export namespace Bookname{
    export class Snows{
        name:any;
        constructor(bookname){
            console.log(bookname);
        }
    }
    export class Adventure{
        name:any;
        constructor(bookname){
            console.log(bookname);
        }
    }
    }
    
    
    
    
    
    export namespace TreeList{
    export class MangoTree{
        name:any;
        constructor(treeName){
            console.log(treeName);
        }
    }
    export class GuvavaTree{
        name:any;
        constructor(treeName){
            console.log(treeName);
        }
    }
    }
    

    bookTreeCombine.ts

    ---compilation part---

    import {Bookname , TreeList} from './namespaceModule';
    import b = require('./namespaceModule');
    let BooknameLists = new Bookname.Adventure('Pirate treasure');
    BooknameLists = new Bookname.Snows('ways to write a book'); 
    const TreeLis = new TreeList.MangoTree('trees present in nature');
    const TreeLists = new TreeList.GuvavaTree('trees are the celebraties');
    
    0 讨论(0)
  • 2020-11-22 09:38

    Small impovement of Albinofrenchy answer:

    base.ts

    export class Animal {
    move() { /* ... */ }
    }
    
    export class Plant {
      photosynthesize() { /* ... */ }
    }
    

    dog.ts

    import * as b from './base';
    
    export class Dog extends b.Animal {
       woof() { }
    } 
    

    things.ts

    import { Dog } from './dog'
    
    namespace things {
      export const dog = Dog;
    }
    
    export = things;
    

    main.ts

    import * as things from './things';
    
    console.log(things.dog);
    
    0 讨论(0)
  • 2020-11-22 09:40

    OP I'm with you man. again too, there is nothing wrong with that answer with 300+ up votes, but my opinion is:

    1. what is wrong with putting classes into their cozy warm own files individually? I mean this will make things looks much better right? (or someone just like a 1000 line file for all the models)

    2. so then, if the first one will be achieved, we have to import import import... import just in each of the model files like man, srsly, a model file, a .d.ts file, why there are so many *s in there? it should just be simple, tidy, and that's it. Why I need imports there? why? C# got namespaces for a reason.

    3. And by then, you are literally using "filenames.ts" as identifiers. As identifiers... Come on its 2017 now and we still do that? Ima go back to Mars and sleep for another 1000 years.

    So sadly, my answer is: nop, you cannot make the "namespace" thing functional if you do not using all those imports or using those filenames as identifiers (which I think is really silly). Another option is: put all of those dependencies into a box called filenameasidentifier.ts and use

    export namespace(or module) boxInBox {} .
    

    wrap them so they wont try to access other classes with same name when they are just simply trying to get a reference from the class sit right on top of them.

    0 讨论(0)
提交回复
热议问题