我有一些代码:

baseTypes.ts

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

dog.ts

import b = require('./baseTypes');

export namespace Living.Things {
  // Error, can't find name 'Animal', ??
  export class Dog extends Animal {
    woof() { }
  }
}

tree.ts

// Error, can't use the same name twice, ??
import b = require('./baseTypes');
import b = require('./dogs');

namespace Living.Things {
  // Why do I have to write b.Living.Things.Plant instead of b.Plant??
  class Tree extends b.Living.Things.Plant {

  }
}

这让人很困惑。我想有一堆外部模块,它们都向同一个命名空间Living.Things贡献类型。这似乎根本不管用——我在dogs.ts中看不到Animal。我必须写出完整的命名空间名字b。生物。植物。树。它不能跨文件在同一个名称空间中组合多个对象。我怎么做呢?


当前回答

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 {
    }
}

其他回答

关于这个主题,我看到的一些问题/评论听起来好像这个人在使用Namespace,他们的意思是“模块别名”。正如Ryan Cavanaugh在他的评论中提到的,你可以有一个'Wrapper'模块重新导出几个模块。

如果您真的想从相同的模块名/别名导入它,可以将包装器模块与tsconfig.json中的路径映射结合起来。

例子:

- path / to / CompanyName t.s.产品- Foo。

export class Foo {
    ...
}

- path / to / CompanyName。产品- t.s.酒吧。

export class Bar {
    ...
}

- path / to / CompanyName。产品/ 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'

注意:输出.js文件中的模块解析需要以某种方式处理,例如使用这个https://github.com/tleunen/babel-plugin-module-resolver

示例:.babelrc处理别名解析:

{
    "plugins": [
        [ "module-resolver", {
            "cwd": "babelrc",
            "alias": {
                "CompanyName.Products": "./path/to/typescript/build/output/CompanyName.Products/index.js"
            }
        }],
        ... other plugins ...
    ]
}

试试这个命名空间模块

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

——编译部分

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');

尝试按文件夹组织:

baseTypes.ts

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

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

dog.ts

import b = require('./baseTypes');

export class Dog extends b.Animal {
    woof() { }
}   

tree.ts

import b = require('./baseTypes');

class Tree extends b.Plant {
}

LivingThings.ts

import dog = require('./dog')
import tree = require('./tree')

export = {
    dog: dog,
    tree: tree
}

main.ts

import LivingThings = require('./LivingThings');
console.log(LivingThings.Tree)
console.log(LivingThings.Dog)

这个想法是你的模块本身不应该关心/知道它们正在参与一个命名空间,但是这以一种紧凑、合理的方式将你的API暴露给消费者,而不知道你正在为项目使用哪种类型的模块系统。

Ryan的回答没有错,但是对于那些来这里寻找如何在正确使用ES6名称空间的情况下维护一个类一个文件结构的人,请参考来自微软的有用资源。

在阅读文档后,我不清楚的一件事是:如何用一个导入导入整个(合并的)模块。

编辑 转回来更新这个答案。TS中出现了几种命名空间的方法。

所有模块类都在一个文件中。

export namespace Shapes {
    export class Triangle {}
    export class Square {}      
}

将文件导入命名空间,并重新分配

import { Triangle as _Triangle } from './triangle';
import { Square as _Square } from './square';

export namespace Shapes {
  export const Triangle = _Triangle;
  export const Square = _Square;
}

// ./shapes/index.ts
export { Triangle } from './triangle';
export { Square } from './square';

// in importing file:
import * as Shapes from './shapes/index.ts';
// by node module convention, you can ignore '/index.ts':
import * as Shapes from './shapes';
let myTriangle = new Shapes.Triangle();

最后一点考虑。您可以为每个文件命名空间

// triangle.ts
export namespace Shapes {
    export class Triangle {}
}

// square.ts
export namespace Shapes {
    export class Square {}
}

但是当一个从同一个名称空间导入两个类时,TS会抱怨标识符重复。此时唯一的解决方案是别名命名空间。

import { Shapes } from './square';
import { Shapes as _Shapes } from './triangle';

// ugh
let myTriangle = new _Shapes.Shapes.Triangle();

这种混叠是绝对可恶的,所以不要这样做。你最好采用上面的方法。就我个人而言,我更喜欢“桶”。

白化病小改善答案:

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);