首页 / Svelte 5 入门教程 / TypeScript 支持

Svelte 5 入门教程

TypeScript 支持

本教程共 50 篇 · 第 38 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

SvelteSvelte 5TypeScript类型svelte-check

38. TypeScript 支持

本节目标:学会在 Svelte 5 组件中使用 TypeScript,掌握 $props() 类型标注、泛型组件、ComponentProps 类型工具和 svelte-check 命令行检查。

在组件中启用 TypeScript

<script> 标签加 lang="ts" 就能写 TypeScript:

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

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

<button onclick={() => alert(greet(name))}>
	{name}
</button>

Svelte 的 VS Code 插件支持完整的类型检查,你写错类型时编辑器会立即标红。

Note

lang="ts" 支持的是 TypeScript 的纯类型特性——类型标注、接口声明等编译后消失的东西。需要生成代码的特性(如 enum)需要额外配置预处理器。SvelteKit 项目默认已配好,开箱即用。

给 $props() 加类型

$props() 返回一个对象,你可以像普通变量一样给它加类型标注:

<script lang="ts">
	interface Props {
		title: string;          // 必填
		count?: number;         // 可选
		onclick?: () => void;   // 回调函数
	}

	let { title, count = 0, onclick }: Props = $props();
</script>

<h1>{title}</h1>
<p>点击次数:{count}</p>

如果组件接收 snippet(内容插槽),用 Snippet 类型:

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

	interface Props {
		children: Snippet;           // 无参数 snippet
		itemRenderer: Snippet<[number]>; // 带参数 snippet
	}

	let { children, itemRenderer }: Props = $props();
</script>

{@render children()}
{#each [1, 2, 3] as item}
	{@render itemRenderer(item)}
{/each}

泛型组件

有时候组件需要处理泛型类型。比如一个列表组件,接收 items 数组和一个 select 回调,两者应该操作同一种类型。给 script 标签加 generics 属性:

<script lang="ts" generics="Item extends { id: string }">
	interface Props {
		items: Item[];
		onSelect: (item: Item) => void;
	}

	let { items, onSelect }: Props = $props();
</script>

{#each items as item (item.id)}
	<button onclick={() => onSelect(item)}>
		{item.id}
	</button>
{/each}

generics 的内容就是你写在泛型函数 <...> 之间的部分。可以用多个泛型参数,也可以用 extends 约束。

使用时类型会自动推导:

<script lang="ts">
	import List from './List.svelte';

	interface User { id: string; name: string }

	let users: User[] = [
		{ id: '1', name: '张三' },
		{ id: '2', name: '李四' }
	];

	function handleSelect(user: User) {
		console.log(user.name);
	}
</script>

<List items={users} onSelect={handleSelect} />
Tip

泛型组件在做 UI 组件库时特别有用。比如 Select<T>Table<T> 这类通用组件,泛型保证传入的数据类型和回调参数类型一致。

$state 类型标注

$state 的类型标注和普通变量一样:

let count: number = $state(0);
let name: string = $state('hello');
let items: string[] = $state([]);

如果不给初始值,类型会包含 undefined

// 类型是 number | undefined
let count: number = $state(); // 报错!

如果确定会在使用前赋值,用 as 断言:

class Counter {
	count = $state() as number;

	constructor(initial: number) {
		this.count = initial;
	}
}

Component 和 ComponentProps 类型

Svelte 5 提供了两个工具类型,用于在组件之间传递类型信息。

Component 类型表示一个 Svelte 组件的构造器,可以约束动态组件:

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

	interface Props {
		dynamicComp: Component<{ label: string }>;
	}

	let { dynamicComp }: Props = $props();
</script>

<dynamicComp label="点击" />

ComponentProps 类型可以提取某个组件的 Props 类型:

import type { ComponentProps } from 'svelte';
import MyComponent from './MyComponent.svelte';

// MyComponentProps 等同于 MyComponent 的 Props 接口
type MyComponentProps = ComponentProps<typeof MyComponent>;

// 用在包装函数上
function renderWithDefaults(
	component: typeof MyComponent,
	props: Partial<ComponentProps<typeof MyComponent>>
) {
	// ...
}
Note

Svelte 4 中组件类型是 SvelteComponent,Svelte 5 改为 Component。迁移时需要替换类型引用。

包装原生元素的类型

写一个包装 <button> 的组件时,你可能想暴露 button 的所有原生属性。用 svelte/elements 提供的类型:

<script lang="ts">
	import type { HTMLButtonAttributes } from 'svelte/elements';

	let { children, ...rest }: HTMLButtonAttributes = $props();
</script>

<button {...rest}>
	{@render children?.()}
</button>

不是所有元素都有专属类型定义。没有的话用 SvelteHTMLElements

<script lang="ts">
	import type { SvelteHTMLElements } from 'svelte/elements';

	let { children, ...rest }: SvelteHTMLElements['div'] = $props();
</script>

<div {...rest}>
	{@render children?.()}
</div>

增强 DOM 类型

用了自定义属性或实验性 API 时,TypeScript 会报”不认识这个属性”。你可以通过模块增强来扩展类型定义:

// additional-svelte-typings.d.ts
import { HTMLButtonAttributes } from 'svelte/elements';

declare module 'svelte/elements' {
	// 给 button 加自定义属性
	export interface HTMLButtonAttributes {
		'custom-attr'?: string;
	}

	// 给所有元素加全局属性
	export interface HTMLAttributes<T> {
		'data-theme'?: string;
	}
}

export {}; // 确保是模块增强而非覆盖
Tip

确保这个 .d.ts 文件在 tsconfig.jsoninclude 范围内。修改后可能需要重启编辑器才能生效。

tsconfig 配置

使用 TypeScript 时,tsconfig.json 需要注意几个设置:

{
	"compilerOptions": {
		"target": "ES2015",
		"verbatimModuleSyntax": true,
		"isolatedModules": true
	}
}
设置原因
targetES2015+避免类被编译成函数
verbatimModuleSyntaxtrue保持 import 原样,不自动转换
isolatedModulestrue每个文件独立编译,适配 Vite 的单文件转译

SvelteKit 项目创建时已经配好这些,通常不需要手动改。

svelte-check

svelte-check 是命令行类型检查工具,相当于在终端运行编辑器里的类型检查:

npx svelte-check

它检查 .svelte.svelte.js/.ts 文件中的类型错误和 a11y 警告。常用选项:

# 只检查不输出 tsconfig
npx svelte-check --tsconfig ./tsconfig.json

# 输出为人类可读详细格式
npx svelte-check --output human-verbose

# 监听文件变化
npx svelte-check --watch
Tip

svelte-check 加到 CI/CD 流程中,在代码合并前自动拦截类型错误。在 package.json 里加一个脚本:"check": "svelte-check --tsconfig ./tsconfig.json"

本节回顾

  • <script lang="ts"> 启用 TypeScript,支持纯类型特性
  • $props() 用接口标注类型,snippet 用 Snippet 类型
  • generics 属性声明泛型组件,适合通用 UI 组件库
  • ComponentComponentProps 用于组件间的类型约束和提取
  • svelte/elements 提供原生 HTML 元素的属性类型
  • svelte-check 在命令行做类型检查,推荐接入 CI