Slidev TwoSlash 代码块集成指南:在幻灯片中内联与悬停展示 TypeScript 类型
2026/9/10 9:48:16 网站建设 项目流程

Slidev TwoSlash 代码块集成指南:在幻灯片中内联与悬停展示 TypeScript 类型

【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev

TwoSlash 是面向 TypeScript 演示与教学的代码高亮增强工具,将其集成进 Slidev 后,你的ts代码块可以在悬停时弹出完整类型信息、通过^?标记内联展开类型推导,并自动标注类型错误与警告。本指南以 skills/slidev/references/code-twoslash.md 为脉络,结合仓库中的官方文档、语法解析源码与官方模板,完整讲解如何在 Slidev 中启用、配置与深度使用 TwoSlash,读完即可直接产出带“实时类型”的代码型演示文稿。

TwoSlash 在 Slidev 中的定位

TwoSlash 是一套渲染 TypeScript 代码块、把类型信息以悬停气泡或内联形式呈现的工具链,对 JavaScript / TypeScript 主题的技术分享与教学课件尤其适用。Slidev 从 v0.46.0 起正式支持该能力,完整特性介绍见 docs/features/twoslash.md。

需要先澄清一个常见误区:Slidev 的高亮能力默认由 Shiki 驱动,TwoSlash 并不是另一套独立的渲染引擎,而是叠加在 Shiki 语法高亮之上的类型编译与展示层——代码着色仍由 Shiki 完成,TwoSlash 则负责调用 TypeScript 编译器解析代码、计算类型并注入标注。因此在依赖层面,@slidev/slidev同时引入@shikijs/twoslash@shikijs/vitepress-twoslash,并以typescript作为编译后端的依赖来源(见 packages/slidev/package.json)。

核心用法:在语言标识符后追加twoslash

使用方式非常轻量:把twoslash追加到代码块的语言标识符之后即可。以下面这段来自 Vue 官方风格的示例来说:

```ts twoslash import { ref } from 'vue' const count = ref(0) // ^? ```

渲染结果中,// ^?注释正下方的光标位置会被替换成该表达式的完整推导类型,同时代码会呈现出 Twoslash 特有的粉红/紫色类型标注样式:

import { ref } from 'vue' const count = ref(0) // ^?

对应的展示效果可以查看官方模板 packages/slidev/template.md 中 "Code" 一节的真实呈现。值得注意的是:// ^?标注缩进无需与表达式严格对齐,Twoslash 会依据行号定位目标表达式。

四种核心能力

根据参考文档与仓库实现,Slidev 中的 TwoSlash 提供以下能力:

  • 悬停类型信息(Hover):在浏览器演示页面中把鼠标悬停到任意变量、属性或表达式上,即可弹出完整的类型签名、泛型展开与文档注释;
  • 内联类型标注(^?:通过// ^?注释把某一行表达式的推导类型直接“写死”在代码里,适合逐步讲解类型推导过程;
  • 错误与警告展示:编译器报告的诊断信息会以行内标注形式直接呈现在代码块中,例如把doubled.value = 2这类对只读计算属性赋值(computed返回WritableComputedRef的差异场景下)的异常直观标出;
  • 完整 TypeScript 编译器集成:类型解析基于真实的 TypeScript 编译器而非正则匹配,因此泛型、条件类型、模块解析等复杂推断同样准确。

悬停 vs 内联:两种展示形态的分工

  • 悬停(hover)面向演示现场的实时探索:观众把鼠标移到标识符上即可查看类型,演讲者无需把每个类型都写进代码,适合“代码本身干净、重点口头讲解”的场景;
  • 内联(^?面向讲解型课件:把关键推导结果固化在幻灯片上,即使不在演示状态、或听众只看静态导出的 PDF / 网页,也能看到“这行代码是什么类型”。

全局开关与模式控制:twoslash前端配置项

TwoSlash 并非每次都要开启——它会在编译期间真实运行 TypeScript 编译器,对大型工程会带来额外耗时。Slidev 因此提供一个顶层 frontmatter 配置twoslash,在 packages/types/src/frontmatter.ts 中其类型定义为:

twoslash?: boolean | 'dev' | 'build'

各取值含义如下:

取值行为
true在开发服务器与最终构建中均启用 TwoSlash(与默认值一致)
false全局关闭 TwoSlash,即便代码块标注了twoslash也不会触发
'dev'仅开发预览时启用,构建产物不携带类型标注
'build'仅最终构建产物启用,本地开发时不进行类型编译以加快热更新

配置示例:

--- twoslash: 'dev' # 只在本地开发预览时启用类型编译 ---

需要说明的是:该选项的默认值为true。默认配置的注册见 packages/parser/src/config.ts(twoslash: true),类型注释同样标明@default true。因此开箱即用——你不必做任何配置,只要在代码块上写ts twoslash即可生效。若你的工程较大、类型编译拖慢了热更新,再考虑用'dev'false收敛。

源码视角:TwoSlash 是如何接入渲染管线的

要理解 TwoSlash 在 Slidev 中的真实工作方式,需要看代码块的高亮/解析模块 packages/slidev/node/syntax/shiki.ts。该模块负责把 Markdown 中的代码块交给 Shiki 做语法高亮,TwoSlash 正是作为Shiki Transformer挂入这条管线的。其中关键实现如下。

显式触发:explicitTrigger: true

return transformerTwoslash({ explicitTrigger: true, twoslashOptions: { compilerOptions: { ignoreDeprecations: '6.0', }, handbookOptions: { noErrorValidation: true, }, }, })

explicitTrigger: true意味着 TwoSlash只在显式声明了twoslash标识的代码块上运行编译器,其余普通代码块不受影响——这是它能与全站语法高亮共存的前提:默认情况下 Shiki 仍会为所有代码块着色,但只有打了ts twoslash标记的块才会付出“跑一遍 TypeScript 编译器”的代价。同时它保证未启用 TwoSlash 的代码块不会被注入额外 DOM,导出的静态幻灯片也更干净。

错误的宽容处理:noErrorValidation: true

handbookOptions.noErrorValidation被置为true,表示代码中的类型错误不会阻断渲染流程。这有两个直接后果:其一,即使示例代码存在类型错误,幻灯片仍能正常生成,不会因为一个报错卡死整个演示;其二,错误本身会以行内诊断的形式保留显示,恰好可以作为“演示错误类型”的教学素材。在写讲稿时若有意识地保留一个错误示例,观众能直接看到编译器的报错文案,这正是 TwoSlash 相对普通高亮的核心卖点。

按需装载语言与编译器

getTwoslashTransformer()内通过Promise.all先触发shiki.codeToHast('', { lang: 'js' })lang: 'ts'两条预加载,再动态import('@shikijs/vitepress-twoslash')。从该结构可以推断:TwoSlash transformer 采用异步懒加载策略,语言包与编译器模块只在真正需要时引入,避免拖慢无 TwoSlash 幻灯片的启动速度。

模式门控:开发/构建分离

Transformer 是否真正注入由以下条件决定:

(config.twoslash === true || config.twoslash === mode) && await getTwoslashTransformer(), (config.twoslash === true || config.twoslash === mode) && transformerTwoslashConditional(),

其中mode是当前构建阶段('dev''build')。也就是说 frontmatter 里的twoslash: 'dev'/'build'在这里被消费——只有当全局开关为true,或恰好等于当前阶段时,类型编译与标注注入才会发生。这从实现上印证了上一节的取值语义。

跨页溢出修复:弹层只在当前页展示

由于 Slidev 会将相邻幻灯片预渲染以保证切换动画流畅,若类型气泡随离屏幻灯片一起渲染,会出现弹层“穿透”到当前页或遮挡下方内容的问题。源码中的transformerTwoslashConditional()(针对 issue #2202 的修复)会在生成阶段遍历 Twoslash 注入的 DOM 树,把气泡容器的:shown属性改写为:

node.properties[':shown'] = '$nav.currentPage === $page'

即类型弹层仅当该幻灯片是当前正在展示的一页时才可见,其余离屏页面的气泡一律隐藏。这也是为什么你在 docs/features/twoslash.md 中能看到一个<div class="py-20" />占位注释——正是为了避免演示页面中下方内容被弹层遮挡而预留的间距技巧,说明该文档本身就是在渲染中验证过的实例。

进阶组合:TwoSlash × 行高亮 × 点击步进

TwoSlash 可与 Slidev 的代码行高亮与点击步进语法组合使用。官方模板 packages/slidev/template.md 中的 "Code" 小节提供了标准示范:

```ts {all|5|7|7-8|10|all} twoslash // TwoSlash enables TypeScript hover information // and errors in markdown code blocks import { computed, ref } from 'vue' const count = ref(0) const doubled = computed(() => count.value * 2) doubled.value = 2 ```

这里的{all|5|7|7-8|10|all}是 Slidev 的点击步进高亮语法(行高亮的完整语法参见 docs/features/line-highlighting.md):每次点击切换一轮焦点行。twoslash关键字与行高亮参数用空格分隔、共存于同一围栏元信息中,互不干扰。

这意味着你可以在同一段代码上叠加两种表达节奏:

  1. 点击步进控制“先看哪几行”的叙事顺序;
  2. TwoSlash负责提供每一步背后“类型发生了什么变化”的即时反馈。

例如先高亮const count = ref(0),观众可悬停看到Ref<number>;再步进到const doubled = computed(...),看到ComputedRef<number>;最后展示doubled.value = 2的赋值错误标注——一个完整的“ref/computed 类型推导 + 只读约束”教学片段就这样在单块代码上完成了。类似的可运行示例还可在 demo/starter/slides.md 中查看。

适用场景与使用建议

TwoSlash 的定位非常聚焦:一切需要把“类型”讲清楚的 TypeScript / JavaScript 教学材料。典型场景包括:

  • Vue / React API 原理课:用refcomputed、泛型工具类型的实时推导结果讲清响应式 API 的返回类型;
  • TypeScript 类型体操:借助// ^?把条件类型、infer、映射类型的结果逐步展开,比口头描述直观得多;
  • 源码走读 / 框架讲解:悬停查看第三方库方法的完整签名,让听众实时看到 IDE 级别的类型信息;
  • 错误驱动教学:故意保留一处类型错误,让编译器诊断直接出现在幻灯片上,配合noErrorValidation的宽容行为,讲解“为什么这行会报错”。

使用时留意以下边界:

  • twoslash关键字只对该围栏内的代码生效,是一种按块显式开启的机制,不会影响其他普通代码块;
  • 类型标注依赖真实 TypeScript 编译,代码块越复杂、依赖越深,构建耗时越长,超大工程建议配合twoslash: 'dev''build'控制编译阶段;
  • 官方模板中的// More at ...注释仅是提示性文字,实际悬停/内联渲染均由 Shiki 的 TwoSlash transformer 自动完成,无需手写任何自定义容器。

延伸阅读

  • 官方功能文档:docs/features/twoslash.md
  • 底层渲染实现:packages/slidev/node/syntax/shiki.ts
  • frontmatter 配置类型定义:packages/types/src/frontmatter.ts 与默认值注册 packages/parser/src/config.ts
  • 可运行的官方示例:packages/slidev/template.md、demo/starter/slides.md
  • 代码块整体语法:docs/guide/syntax.md 中的 Code Blocks 小节,其下还汇总了行号、最大高度等同族特性
  • 行高亮与点击步进语法:docs/features/line-highlighting.md

【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询