如何在 Typescript 文件中导入 Svelte 组件?

Posted

技术标签:

【中文标题】如何在 Typescript 文件中导入 Svelte 组件?【英文标题】:How do you import a Svelte component in a Typescript file? 【发布时间】:2020-10-26 21:44:45 【问题描述】:

是否可以在 Typescript 文件中导入 Svelte 组件并让 Rollup 成功编译它?

以下代码作为 javascript 文件工作,但转换为 Typescript 时出错,因为 TS 编译器不知道如何处理 .svelte 文件:

import Component from './Component.svelte';

const foo = () => new Component( target: document.body );

是否有 rollup-plugin-svelte@rollup/plugin-typescript 的组合可以预处理 Svelte 组件,使 Typescript 编译器可以包含 Svelte 代码?


如果更多上下文有帮助,boardgame.io 包含使用 Svelte 构建的 an in-browser debugging component,它捆绑在普通 JS 客户端和 React 客户端组件中,我们正在尝试更新 our Rollup config这个场景。

【问题讨论】:

打字稿编译器需要了解./Component.svelte模块。你需要定义它。 Rollup 是一个 bundler,它也需要知道如何处理模块,这就是 rollup 的插件的作用。 对 Svelte 的完全 Typescript 支持可能还需要几天时间 - 看看这个 Twitter 线程,它非常接近确认 twitter.com/sveltejs/status/1277235019845644288?s=20 【参考方案1】:

为了扩展 Rich 的回答,我很想研究为什么导入 Svelte 有助于某些设置。

TS 编译器不知道如何处理 .svelte 文件

Svelte 通过在svelte/types/runtime/ambient.d.ts 中分发文件来解决这个问题(至少在撰写本文时的版本3.35.0):

declare module '*.svelte' 
    export  SvelteComponentDev as default  from 'svelte/internal';

这有效地使 TS 编译器分析 .svelte 文件。出于学术兴趣,它还声明了.svelte 文件中的脚本可以访问的所有运行时功能的类型,例如set_attributes()(有关更多信息,请参见svelte/internal)。所以只写declare module '*.svelte' 只会让你获得一部分,因为你还需要那些运行时声明。

因此,要让 TypeScript 编译器处理 .svelte 文件,您需要以一种或另一种方式引用该文件的类型,svelte/types/runtime/ambient.d.ts。它实际上是由包的入口点类型文件(在 Svelte 的 package.jsontypes 字段中指定的值)、types/runtime/index.d.ts 间接引用的,所以同样,您可以引用该入口点类型文件。这样做是最佳实践,因为它可以抵御未来目录结构中的重构。

扩展@tsconfig/svelte/tsconfig.json 可以满足这一点,因为有问题的 tsconfig 文件通过其compilerOptions.types 属性引用了"svelte" 节点模块:


  // ... Omitted...

  "compilerOptions": 
    // ... Omitted...

    "types": ["svelte"]
  

这实际上意味着编译上下文将包含此引用:

/// <reference types="svelte" />

您同样可以自己编写相同的代码行,尽管您也可以扩展 Svelte tsconfig,因为它对未来的 Svelte 演进非常强大。

导入副作用的建议出于同样的原因:

import "svelte";

我发现即使我扩展了 Svelte tsconfig,也没有引用 Svelte 类型。原来这是因为我在我的 tsconfig 中结束了这一行:


  "extends": "@tsconfig/svelte/tsconfig.json",
  
  // ... Omitted...

  "compilerOptions": 
    // ... Omitted...

    "types": ["node"] // This overrides ["svelte"]!
  

我通过将"types": ["node"] 替换为"types": ["node", "svelte"] 来修复它。

【讨论】:

原来这对我很有用,谢谢!【参考方案2】:

尝试将@tsconfig/svelte 添加到您的项目中,然后更新您的 tsconfig.json 文件:


  "extends": "@tsconfig/svelte/tsconfig.json",
  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"],

【讨论】:

谢谢!这似乎让tsc 高兴,但是对于使用 Typescript 的库使用者,没有为 Svelte 入口点输出声明文件,并且在需要导入组件的模块。任何 Typescript 消费者是否还需要 tsconfig 来扩展 @tsconfig/svelte/tsconfig.json 或添加 "types": ["svelte", ...]?或者有没有办法为组件输出类型声明? 不确定——如果它是一个使用组件的库,听起来您可能需要从exclude 数组中删除node_modules 不确定这是否是正确的方法,但我通过将import 'svelte' 添加到我们的主要类型定义中使其工作。 Svelte 必须是一个依赖项(而不是 dev 依赖项)以确保为消费者安装它,但这似乎使环境 *.svelte 模块声明也对消费者可见。 啊,事实上,这样做意味着我们也不需要告诉tsc tsconfig.json 中的 Svelte 类型,因为它们已经被导入提升了。 我刚刚将import 'svelte' 添加到我的一个 ts 文件(根文件)中,并且它起作用了。谢谢@delucis

以上是关于如何在 Typescript 文件中导入 Svelte 组件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 TypeScript 时如何在单个文件组件中导入 Vue?

如何在 TypeScript 中导入 package.json?

如何使用对象解构在 TypeScript 中导入 JSON?

如何在 typescript react-native 项目中导入降价文件?

如何在 React 应用程序的 typescript 文件中导入 js 模块(使用绝对路径)?

如何在 TypeScript 中导入 KnockOut 4?