首页 > 解决方案 > 与同一文件中的类型别名同名的命名空间

问题描述

我遇到了一个可以概括为的模式:

export namespace Foo {
    export enum Bar {}
}
export type Foo = Omit<typeof Foo, 'Bar'>

(这里的原始代码。)根据我对打字稿的基本理解,我认为这样做是:

  1. 声明一个命名空间Foo
  2. 考虑typeof Foo从该命名空间创建一个类型。
  3. 从 2 中创建的类型中省略Bar,并将此类型别名为 identifier Foo

到目前为止一切都很好,我认为,但如果我错了,请纠正我。在这一点上,事情进入了我的魔法领域。这是因为当Foo从另一个文件导入时,不知何故神奇地Foo导入了命名空间,而不是类型别名Foo。我的问题是:

  1. 由于类型推断魔术,第二个文件是否导入了正确的文件,Foo或者我应该知道这里发生的其他事情?
  2. 回到声明两个Foos 的原始文件,我们有两个同名的东西没有名称冲突,这很奇怪吗?命名空间是对象而类型别名是类型这一事实是否避免了冲突?
  3. 这是 TypeScript 中的常见模式吗?这是一个很好的模式吗?我应该写这样的代码吗?

标签: typescript

解决方案


关于代码在做什么,您的想法是正确的。

  1. 是的,编译器会根据用法推断它是引用类型别名还是命名空间。

例如:https ://github.com/rokoroku/react-redux-typescript-boilerplate/blob/master/src/app/components/TodoList/index.tsx#L10

在这里,TodoActions用作类型,因此编译器知道它引用了导出的类型别名。

另一个例子:https ://github.com/rokoroku/react-redux-typescript-boilerplate/blob/master/src/app/reducers/todos.ts#L16

在这里,TodoActions.Type.ADD_TODO用于创建属性,因此编译器再次知道它引用了命名空间。

如果您将鼠标悬停在 VS Code 中的标识符上,您实际上可以看到这一点:

类型

命名空间

  1. 和 3.) 一开始可能有点令人困惑,但这是预期的行为。不过,我个人会避免它,因为它会引起不必要的混乱。

以下文章解释了您的确切问题:https ://www.typescriptlang.org/docs/handbook/declaration-files/deep-dive.html


推荐阅读