Skip to content

Typst 入门笔记

最近写课程报告时觉得 LaTeX 的编译速度实在慢的难以忍受,于是粗略体验了一下 Typst,感觉它的设计理念非常现代——把「排版」当成一门编程语言来做。

为什么选择 Typst

维度LaTeXTypst
编译速度慢(大型文档几十秒)快(增量编译,毫秒级)
错误提示宏展开后的 cryptic error清晰的源码级报错,带行号
包管理靠系统包管理器或手动下载内置包管理器,类似 Cargo/NPM
脚本能力宏编程,学习曲线陡峭真正的脚本语言(类 Rust 语法)
实时预览需外部工具(如 Overleaf)自带 typst watch,原生支持
生态系统极其丰富较新,但核心场景已覆盖

安装与使用

说到这里不得不吐槽 Latex 的安装实在是太麻烦了一些,1~2G 的安装包,搭配上经常出现的网络问题,对尤其是新手用户相当不友好。

好在这些在 Typst 里面都被妥善解决了,Typst 非常轻量,你甚至只需要安装一个 VSCode 插件就能使用。

当然你也可以选择获取他的二进制文件或在官网提供的 Typst Playground 使用。Typst 支持实时预览,其渲染速度和 Markdown 不相上下,在 Latex 惯用者看来这种体验不亚于古人第一次接触现代科技。

语法模式

Typst 有三种语法模式:Markup、math 和 code。Markup 模式是 Typst 文档的默认模式,math 模式用于编写数学公式,code 模式用于使用 Typst 的脚本功能。

你可以在任何时候通过参考下表切换到特定模式:

模式语法示例
Code# 开头数字:#(1 + 2)
Math$..$包裹公式 $-x$$x$ 的相反数
Markup[..]包裹标记 let name = [*Typst!*]

一旦你使用 # 进入 code 模式,除非在中间切换回 markup 或 math 模式,否则不需要再使用其他 #

基本语法

Typst 的标记语法非常直观,和 Markdown 有几分相似:

typ
= 一级标题
== 二级标题
=== 三级标题

这是普通段落,*粗体*_斜体_、`行内代码` 都很自然。

- 无序列表项
- 另一项

+ 有序列表项
+ 另一项

#figure(
  image("diagram.png", width: 80%),
  caption: [一个示例图],
)

进阶语法

标签与引用

Typst 的标签(label)和引用系统比 LaTeX 更直观:

typ
= 第一章 <ch1-intro>

见第一章 @ch1-intro,或者第 @ch1-intro 页。

#set heading(numbering: "1.1")

= 引言 <intro>

== 背景 <intro-bg>

@intro-bg 中我们讨论了相关工作。

引用自动带上当前「上下文标题」作为前缀,无需手动维护编号。

图表与浮动体

typ
#figure(
  table(
    columns: 3,
    table.header([Method], [Accuracy], [Time]),
    [SGD], [0.82], [1.2s],
    [Adam], [0.91], [2.1s],
    [AdamW], [0.93], [2.3s],
  ),
  caption: [优化器对比实验结果],
  supplement: [表],
)
// supplement 指定浮动体前缀文字(表/图/代码块等)

#figure 生成的是「浮动体」,可以指定 placement 控制位置:

typ
#figure(..., placement: auto)    // 默认:当前位置或页顶
#figure(..., placement: top)    // 强制放在页面顶部
#figure(..., placement: bottom)  // 强制放在页面底部
#figure(..., placement: float)  // LaTeX 风格的完全浮动

脚注

typ
这是正文。#footnote[这是脚注内容。]

脚注会自动编号,上标标记点击可跳转。

参考文献

Typst 使用 BibTeX 格式的 .bib 文件,配合 #bibliography() 渲染:

typ
#set text(lang: "zh")
#bibliography("refs.bib", style: "gb-7714-2015")

在正文中引用:

typ
Transformer 的提出革新了自然语言处理领域 @vaswani2017attention

布局命令

页面整体布局设置:

typ
#set page(
  paper: "a4",
  margin: 2.5cm,
  header: [My Document],
  footer: [Page #counter(page).of()],
)

#set text(lang: "zh", size: 12pt, font: ("Source Han Sans", "Noto Sans"))

#set par(justify: true, first-line-indent: 2em)

= 章节标题

首段不缩进,正文两端对齐,这是中文学术写作的常见格式。

多栏布局

typ
#set page(columns: 2, gutter: 1.5em)

= 导论

这里是第一栏的内容。Typst 会自动把内容排入多栏,
直到显式换栏或新页面。

#colbreak()

这里是第二栏的内容。

条件与循环

Typst 的脚本语言支持完整的条件与循环:

typ
#let scores = (85, 92, 78, 96, 88)

#for (i, s) in scores.enumerate() {
  if s >= 90 {
    text("[优] ", weight: "bold", fill: red)
  } else if s >= 80 {
    text("[良] ", weight: "medium", fill: orange)
  } else {
    text("[及] ", fill: gray)
  }
  [学生 #i: #s 分]
}

自定义函数

把常用模式封装成可复用函数:

typ
#let info-box(title, body) = {
  block(
    fill: rgb("#f0f0f0"),
    inset: (x: 12pt, y: 8pt),
    radius: 6pt,
    width: 100%,
  )[
    #text(weight: "bold")[#title]
    #body
  ]
}

#info-box("注意", [请在提交前仔细检查所有引用。])

样式层 #show 规则

#show 可以对特定元素批量应用样式,类似 CSS 的选择器:

typ
// 所有引用链接设为蓝色
#show link: it => text(fill: blue, it)

// 所有一级标题改为居中
#show heading.where(level: 1): it => {
  align(center, strong(it))
}

// 特定标签应用特殊样式
#show <warning>: it => {
  block(
    stroke: (left: 4pt + red),
    left-edge: 0pt,
    inset: (left: 12pt),
    it,
  )
}

这相当于 Typst 的「伪类选择器」,比 LaTeX 的 \renewcommand 直观得多。

颜色与绘图

Typst 内置向量绘图能力,无需额外工具:

typ
#import "draw@vector*: vector"

#context {
  let w = 100pt
  let h = 60pt
  let arrow = (start: (0pt, 0pt), end: (w, h), stroke: 2pt)

  vector.draw(
    arrow,
    vector-arrow(start: (w, 0pt), end: (0pt, h)),
  )
}

颜色可以直接用 RGB、CMYK 或命名色:

typ
#rect(fill: rgb("#3B82F6"), width: 2cm)
#rect(fill: cyan, width: 2cm)
#rect(fill: cmyk(0.5, 0, 0, 0), width: 2cm)

数学公式

Typst 的数学模式同样用 $ 包裹,但语法做了大量简化:

含义LaTeXTypst
行内公式$x^2$$x^2$
行间公式$$\sum_{i=1}^n i$$$ sum_(i=1)^n i $
分数\frac{a}{b}$a / b$$(a b) / c$
根号\sqrt{x}$sqrt(x)$
积分\int_0^1 x \,dx$integral_0^1 x dif x$
极限\lim_{x \to 0}$lim_(x -> 0)$
矩阵\begin{pmatrix}...\end{pmatrix}$mat(1, 2; 3, 4)$
多行对齐align* 环境直接写多行,用 & 对齐

Typst 的公式语法有几个显著特点:

  1. 空格敏感$x^2$$ x^2 $ 的区别在于,后者两侧有空格时表示「显示模式」(display math),类似 LaTeX 的 $$...$$
  2. 函数式调用sqrt(x)mat(...) 等采用统一的函数语法。
  3. 变量处理:单独的字母被视为变量如 abc;多字符则被视为函数或其他符号,如 alpha 被解析为 ;如果你想使用多字符作为变量名可以使用引号包裹,如 "signal"
  4. 隐式乘法2x 会被正确解析为 ,不需要写成 2*x

一个更复杂的例子:

typ
$f(a,b) = integral_0^1 (a x^2 + b) dif x
        = a / 3 + b.$

编译后得到一个居中的行间公式,等号处的自动对齐非常优雅。

脚本与自动化

Typst 内嵌了一套完整的脚本语言,这让动态生成内容变得异常简单。例如,自动计算表格行的平均值:

typ
#let data = ((1, 2, 3), (4, 5, 6), (7, 8, 9))

#table(
  columns: 4,
  table.header([A], [B], [C], [Avg]),
  ..data.map(row => {
    let avg = row.sum() / row.len()
    row.map(str).concat((str(avg),))
  }).flatten()
)

这种程度的脚本能力在 LaTeX 里需要借助 pgfplotstable 或外部 Python 脚本才能实现,而在 Typst 中是原生支持。

一个完整的最小示例

typ
#set page(margin: 2.5cm)
#set text(font: "Linux Libertine", size: 12pt)
#set heading(numbering: "1.1")

= 引言

本文档由 Typst 生成。

= 方法

我们考虑如下优化问题:

$ min_x f(x) quad "s.t." quad g(x) <= 0. $

= 结论

确实挺不错的。

#bibliography("refs.bib")

仅十几行就完成了一篇带编号标题、数学公式和参考文献的小型论文框架。

不足

目前 Typst 仍是一个较为年轻的项目,还是不如 Latex 成熟和完整。语法快速迭代,稳定性可能相对不足,社区与生态也尚在建立之中。另外,体验下来我个人觉得对中文的支持还有待提高,有些英文和中文的书写习惯上的差异未完全解决。

总结

总体来说,Typst 虽然好用但目前尚不够完整。我认为它目前的定位是处于 Latex 与 Word 之间的一个东西:比起 Latex 更加轻量易用,比 Word 排版更加稳定。

如果你和我一样,用来写课程报告、技术文档或简历,一方面不想被 Word 的排版折磨,另一方面又觉得使用 Latex 有些「割鸡焉用牛刀」,那么 Typst 确实值得一试。但如果你是要投稿期刊论文,现阶段可能许多期刊不会提供 Typst 模板和相关支持,还是建议选择 Latex 作为工具。

不过我仍然非常欣赏这门新兴的排版语言,简单高效且好玩,希望它能够快速发展到完全替代 Latex 的地步。

参考

Typst 文档