在 TypeScript 中使用导入类型的环境声明
Posted
技术标签:
【中文标题】在 TypeScript 中使用导入类型的环境声明【英文标题】:Ambient declaration with an imported type in TypeScript 【发布时间】:2017-12-19 08:33:13 【问题描述】:我的 TypeScript 项目中有一个声明文件,如下所示:
// myapp.d.ts
declare namespace MyApp
interface MyThing
prop1: string
prop2: number
这很好用,我可以在我的项目中的任何地方使用这个命名空间,而无需导入它。
我现在需要从 3rd 方模块导入一个类型并在我的环境声明中使用它:
// myapp.d.ts
import SomeType from 'module'
declare namespace MyApp
interface MyThing
prop1: string
prop2: number
prop3: SomeType
编译器现在抱怨它找不到命名空间“MyApp”,可能是因为导入阻止它成为环境。
是否有一些简单的方法可以在使用 3rd-party 类型的同时保留声明的环境性?
【问题讨论】:
@RomanStarkov 这对于任何任意库来说都是不可能的,你有一个特定的吗? @TitianCernicova-Dragomir 比如说luxon
,它带有打字功能,看起来就像这里的示例代码 - import DateTime from 'luxon'
。
【参考方案1】:
很遗憾,没有。正如您已经发现这仅适用于内部代码,例如没有外部依赖。您应该导出命名空间,或者导出类并使用 ES6 模块。但两者都会导致你需要import
你的东西。正如我所相信的那样,您试图避免的事情。
就个人而言,我发现在整个代码中实际使用导入(甚至是内部)更令人欣慰。原因很简单,当打开特定文件(类)时,它的所有依赖项都立即可见。
问题"How to use namespaces with import in TypeScript" 已经解决了一个完整的示例。
其他人请注意:“内部可用的命名空间”也是我不认为这是一个重复问题的原因。
【讨论】:
【参考方案2】:是的,有办法。在 TypeScript 2.9 中使用 import() a type 变得更容易,但在早期版本的 TypeScript 中也可以。
以下文件是一个脚本。在脚本中声明的东西被添加到全局范围。这就是为什么您可以使用 MyApp.MyThing
而无需导入它。
// myapp.d.ts
declare namespace MyApp
interface MyThing
prop1: string;
prop2: number;
脚本的局限性在于它们不能导入任何东西;当你添加一个import
时,脚本就变成了一个模块。我认为至少可以说很奇怪,但事实就是如此。重要的是 module 中定义的事物的范围是该模块,而不是添加到全局范围内。
但是,模块也可以将声明添加到全局范围,方法是将它们放入global
:
// myapp.d.ts
import SomeType from 'module';
declare global
namespace MyApp
interface MyThing
prop1: string;
prop2: number;
prop3: SomeType;
此文件是一个模块,但它在全局范围内添加了MyApp.MyThing
的声明,因此您仍然可以在其他TypeScript 代码中使用MyApp.MyThing
而无需导入它。
请注意,使用.d.ts
扩展名与您无需导入即可访问界面无关。上述两个文件都可能是 .ts
文件,并且行为仍然完全相同。
【讨论】:
谢谢。我一直在寻找这个解决方案一个多小时。为什么很难与将符号添加到全局范围但无法使用常规模块导入的环境集成,这超出了我的理解,尤其是因为它似乎是一种常见的要求...... 把它包裹在global
中确实需要更多人知道。这是一个非常常见的情况,很多答案都忽略了这个简单的修复。
2.9 功能是否允许以某种方式将导入的模块定义中的所有内容声明为具有外部模块格式的全局(例如所有类型、接口、变量)?
我希望我能投票 1000 次。我一直在打结。
这仍然需要在某个地方导入 myapp.d.ts 才能使全局增强起作用?【参考方案3】:
从 TS 2.9 开始,import()
可以做到这一点:
// myapp.d.ts
declare type SomeType = import('module').SomeType;
declare type SomeDefaultType = import('module-with-default-export').default;
declare namespace MyApp
interface MyThing
prop1: string;
prop2: number;
prop3: SomeType | SomeDefaultType;
【讨论】:
declare type Foo = import('someModule').default
给我一个错误,即使"someModule"
定义了默认导出:“命名空间 'SomeModule' 没有导出的成员 'default'”。【参考方案4】:
不知道您是否仍在寻找答案,但这是处理它的正确方法,并且仍然能够例如定义通用模块,而不仅仅是命名空间: (original answer this is based on)
// myapp.d.ts
declare namespace MyApp
import SomeType from 'module'
interface MyThing
prop1: string
prop2: number
prop3: SomeType
【讨论】:
这是不正确的。至少不再使用 Typescript 3.8/3.9。它会给你一个错误Import declarations in a namespace cannot reference a module.
以上是关于在 TypeScript 中使用导入类型的环境声明的主要内容,如果未能解决你的问题,请参考以下文章
typeScript声明文件的一个注意点:不能使用导入导出语法
React,Typescript - 找不到模块...或其相应的类型声明