跳至主要内容

其他

TypeScript

在 GitHub 上编辑此页面

您可以在 Svelte 组件中使用 TypeScript。IDE 扩展(例如 Svelte VSCode 扩展)将帮助您在编辑器中捕获错误,而 svelte-check 在命令行中执行相同的操作,您可以将其集成到 CI 中。

设置

要在 Svelte 组件中使用 TypeScript,您需要添加一个预处理器,该预处理器将 TypeScript 转换为 JavaScript。

使用 SvelteKit 或 Vite

入门的最简单方法是通过键入 npm create svelte@latest,按照提示并选择 TypeScript 选项来构建一个新的 SvelteKit 项目。

svelte.config.js
ts
import { vitePreprocess } from '@sveltejs/kit/vite';
const config = {
preprocess: vitePreprocess()
};
export default config;

如果您不需要或不想要 SvelteKit 提供的所有功能,则可以通过键入 npm create vite@latest 并选择 svelte-ts 选项来构建一个 Svelte 风格的 Vite 项目。

svelte.config.js
ts
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const config = {
preprocess: vitePreprocess()
};
export default config;

在两种情况下,都会添加带有 vitePreprocesssvelte.config.js。Vite/SvelteKit 将从这个配置文件中读取。

其他构建工具

如果你使用的是 Rollup 或 Webpack 等工具,请安装它们各自的 Svelte 插件。对于 Rollup,是 rollup-plugin-svelte,对于 Webpack,是 svelte-loader。对于两者,你需要安装 typescriptsvelte-preprocess,并将预处理器添加到插件配置中(有关更多信息,请参阅各自的 README)。如果你正在启动一个新项目,你还可以使用 rollupwebpack 模板从脚本中构建设置。

如果你正在启动一个新项目,我们建议你使用 SvelteKit 或 Vite

<script lang="ts">

要在 Svelte 组件中使用 TypeScript,请在 script 标签中添加 lang="ts"

<script lang="ts">
	let name: string = 'world';

	function greet(name: string) {
		alert(`Hello, ${name}!`);
	}
</script>

Props

Props 可以直接在 export let 语句中输入

<script lang="ts">
	export let name: string;
</script>

Slots

Slot 和 slot prop 类型是从传递给它们的 slot prop 类型推断出来的

<script lang="ts">
	export let name: string;
</script>

<slot {name} />

<!-- Later -->
<Comp let:name>
	<!--    ^ Inferred as string -->
	{name}
</Comp>

Events

事件可以使用 createEventDispatcher 输入

<script lang="ts">
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher<{
		event: null; // does not accept a payload
		click: string; // has a required string payload
		type: string | null; // has an optional string payload
	}>();

	function handleClick() {
		dispatch('event');
		dispatch('click', 'hello');
	}

	function handleType() {
		dispatch('event');
		dispatch('type', Math.random() > 0.5 ? 'world' : null);
	}
</script>

<button on:click={handleClick} on:keydown={handleType}>Click</button>

增强内置 DOM 类型

Svelte 提供了所有现有的 HTML DOM 类型的最佳尝试。有时你可能希望使用来自操作的实验性属性或自定义事件。在这些情况下,TypeScript 将抛出一个类型错误,表示它不知道这些类型。如果它是一个非实验性标准属性/事件,这很可能是我们的 HTML 类型 中缺少类型。在这种情况下,欢迎你提出问题和/或修复它的 PR。

如果这是一个自定义或实验性属性/事件,你可以像这样增强类型

additional-svelte-typings.d.ts
ts
declare namespace svelteHTML {
// enhance elements
interface IntrinsicElements {
'my-custom-element': { someattribute: string; 'on:event': (e: CustomEvent<any>) => void };
}
// enhance attributes
interface HTMLAttributes<T> {
// If you want to use on:beforeinstallprompt
'on:beforeinstallprompt'?: (event: any) => any;
// If you want to use myCustomAttribute={..} (note: all lowercase)
mycustomattribute?: any; // You can replace any with something more specific if you like
}
}

然后确保在你的 tsconfig.json 中引用了 d.ts 文件。如果它读起来像 "include": ["src/**/*"] 并且你的 d.ts 文件在 src 中,它应该可以工作。你可能需要重新加载才能使更改生效。

从 Svelte 版本 4.2 / svelte-check 版本 3.5 / VS Code 扩展版本 107.10.0 开始,你还可以通过像这样扩展 svelte/elements 模块来声明类型

additional-svelte-typings.d.ts
ts
import { HTMLButtonAttributes } from 'svelte/elements';
declare module 'svelte/elements' {
export interface SvelteHTMLElements {
'custom-button': HTMLButtonAttributes;
}
// allows for more granular control over what element to add the typings to
export interface HTMLButtonAttributes {
veryexperimentalattribute?: string;
}
}
export {}; // ensure this is not an ambient module, else types will be overridden instead of augmented

实验性高级类型

在更高级的用例中充分利用 TypeScript 的一些功能还缺失,比如为组件实现某个接口、明确指定插槽类型或使用泛型。使用实验性高级类型功能可以实现这些功能。请参阅 此 RFC 了解更多有关如何使用它们的信息。

该 API 是实验性的,并且随时可能更改

限制

标记中没有 TS

你无法在模板的标记中使用 TypeScript。例如,以下代码不起作用

<script lang="ts">
	let count = 10;
</script>

<h1>Count as string: {count as string}!</h1> <!-- ❌ Does not work -->
{#if count > 4}
	{@const countString: string = count} <!-- ❌ Does not work -->
	{countString}
{/if}

响应式声明

你无法使用 TypeScript 为响应式声明指定类型,就像为变量指定类型一样。例如,以下代码不起作用

<script lang="ts">
	let count = 0;

	$: doubled: number = count * 2; // ❌ Does not work
</script>

你无法添加 : TYPE,因为它在此位置是无效语法。相反,你可以将定义移动到正上方的 let 语句

<script lang="ts">
	let count = 0;

	let doubled: number;
	$: doubled = count * 2;
</script>

类型

ComponentConstructorOptions

ts
interface ComponentConstructorOptions<
Props extends Record<string, any> = Record<string, any>
> {}
ts
target: Element | Document | ShadowRoot;
ts
anchor?: Element;
ts
props?: Props;
ts
context?: Map<any, any>;
ts
hydrate?: boolean;
ts
intro?: boolean;
ts
$$inline?: boolean;

ComponentEvents

便捷类型,用于获取给定组件期望的事件。示例

<script lang="ts">
   import type { ComponentEvents } from 'svelte';
   import Component from './Component.svelte';

   function handleCloseEvent(event: ComponentEvents<Component>['close']) {
	  console.log(event.detail);
   }
</script>

<Component on:close={handleCloseEvent} />
ts
type ComponentEvents<Component extends SvelteComponent_1> =
Component extends SvelteComponent<any, infer Events>
? Events
: never;

ComponentProps

便捷类型,用于获取给定组件期望的属性。示例

<script lang="ts">
	import type { ComponentProps } from 'svelte';
	import Component from './Component.svelte';

	const props: ComponentProps<Component> = { foo: 'bar' }; // Errors if these aren't the correct props
</script>
ts
type ComponentProps<Component extends SvelteComponent_1> =
Component extends SvelteComponent<infer Props>
? Props
: never;

ComponentType

便捷类型,用于获取 Svelte 组件的类型。例如,与使用 <svelte:component> 的动态组件结合使用时很有用。

示例

<script lang="ts">
	import type { ComponentType, SvelteComponent } from 'svelte';
	import Component1 from './Component1.svelte';
	import Component2 from './Component2.svelte';

	const component: ComponentType = someLogic() ? Component1 : Component2;
	const componentOfCertainSubType: ComponentType<SvelteComponent<{ needsThisProp: string }>> = someLogic() ? Component1 : Component2;
</script>

<svelte:component this={component} />
<svelte:component this={componentOfCertainSubType} needsThisProp="hello" />
ts
type ComponentType<
Component extends SvelteComponent = SvelteComponent
> = (new (
options: ComponentConstructorOptions<
Component extends SvelteComponent<infer Props>
? Props
: Record<string, any>
>
) => Component) & {
/** The custom element version of the component. Only present if compiled with the `customElement` compiler option */
element?: typeof HTMLElement;
};

SvelteComponent

具有某些次要开发增强功能的 Svelte 组件的基类。在 dev=true 时使用。

可用于创建强类型 Svelte 组件。

示例:

你在 npm 上有一个名为 component-library 的组件库,从中导出了一个名为 MyComponent 的组件。对于 Svelte+TypeScript 用户,你希望提供类型定义。因此你创建了一个 index.d.ts

ts
import { SvelteComponent } from "svelte";
export class MyComponent extends SvelteComponent<{foo: string}> {}

输入此类型定义后,带有 Svelte 扩展的 IDE(如 VS Code)就可以提供智能感知,并在 Svelte 文件中使用 TypeScript 组件

<script lang="ts">
	import { MyComponent } from "component-library";
</script>
<MyComponent foo={'bar'} />
ts
class SvelteComponent<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponent_1<Props, Events> {}
ts
[prop: string]: any;
ts
constructor(options: ComponentConstructorOptions<Props>);
ts
$capture_state(): void;
ts
$inject_state(): void;

SvelteComponentTyped

改为使用 SvelteComponent。有关更多信息,请参阅 PR:https://github.com/sveltejs/svelte/pull/8512

ts
class SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponent<Props, Events, Slots> {}