使用打字稿创建Vue项目时,会包含两个声明文件: shims-vue.d.ts 和 shims.tsx.d.ts 。
//shims-vue.d.ts
declare module "*.vue" {
import Vue from 'vue';
export default Vue;
}
并且:
//shims-tsx.d.ts
import Vue, { VNode } from 'vue';
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
在创建一个小型项目(没有Vue CLI)时,我忘记包含第二个项目(shims.tsx.d.ts),并且我的项目可以编译并按预期运行(没有错误)。
我发现了有关此帖子: https://github.com/vuejs/vue-cli/issues/1198,但希望得到更多说明。
我很好奇这个文件的作用以及为什么包含它?换句话说,如果我不包括此声明文件,我将不得不“破坏”我的应用程序。
谢谢!
答案 0 :(得分:25)
This link是我能找到的唯一体面的解释。基本上,这与Webpack有关。
如果您不使用Webpack,而仅使用Typescript,则执行类似的操作会出错:
import Foo from "./Foo.vue";
因为显然Typescript无法理解.vue
文件-它们实际上不是Typescript模块。
但是,如果您设置了Vue项目,则会发现它一直都在执行。这是如何运作的? Webpack!据我所知(我试图通过学习有关webpack的任何知识来避免精神错乱),这基本上是Webpack的工作-它遍历Javascript / Typescript中的所有import
文件和“捆绑包”它们,即它将它们合并到一个文件中。
但是它可以用“加载器”(可怕的名称)扩展,可以添加以处理特定的文件格式。例如,您可以将其配置为使用CSS加载器。这意味着当它找到
import "./foo.css"
它将CSS捆绑到输出中,并可能添加一些Javascript在运行时将其插入DOM中,或者像这样废话。
无论如何,(我认为)还有*.vue
个文件的加载程序,用于处理这些文件。这就是import Foo from "./Foo.vue"
起作用的原因。为什么我们需要填充文件?
因为打字稿仍然不满意。它对Webpack一无所知,因此当您尝试导入Foo.vue
(它会告诉您Can't find module "./Foo.vue"
)时,它仍然会引发错误。
解决方案是shims-vue.d.ts
。只要文件名以.d.ts
结尾,文件名似乎并不重要。我猜打字稿会在同一目录或类似目录中寻找所有.d.ts
。
无论如何,内容是这样的:
declare module "*.vue" {
import Vue from 'vue';
export default Vue;
}
这基本上意味着:“每次导入名称为*.vue
(支持通配符)的模块时,实际上就不要这样做-而是将其视为具有这些内容”。
这对我来说似乎是这样:如果您执行import Foo from "./Foo.vue"
,则Foo
的类型将为Vue
。似乎没有一种实际上导入Foo
类型的方法。
编辑:实际上,如果您将组件导入另一个.vue
文件中,则我认为它可以工作。如果从.ts
导入,则只会得到Vue
的别名。这在测试中很烦人!我做了another question about this。
答案 1 :(得分:7)
第一个文件可帮助您的IDE了解以.vue
结尾的文件是什么
第二个文件允许您使用.tsx
文件,同时在IDE中启用jsx
sytnax支持以编写JSX样式的打字稿代码。