Typst Functions
Define with #let foo(args) = .... Call with #foo(args) or #foo[content]. First-class values — pass, store, return.
Basic function definition
// Single-argument function
#let greet(name) = [Hello, #name!]
#greet("World") // → "Hello, World!"
// Multi-argument
#let add(a, b) = a + b
#add(2, 3) // → 5
// Content argument (square brackets)
#let alert(content) = block(fill: yellow, inset: 8pt, content)
#alert[*Important* note here]
// Combine value + content args
#let badge(label, content) = block(stroke: 1pt, inset: 4pt)[
*#label:* #content
]
#badge("Note", [Read this first.])Named arguments & defaults
#let highlight(content, color: red, weight: "bold") = {
text(fill: color, weight: weight, content)
}
// Use defaults
#highlight[normal red bold]
// Override one
#highlight(color: blue)[blue bold]
// Override both
#highlight(color: green, weight: "regular")[green normal]Variadic arguments
// Capture all positional args
#let columns(..items) = grid(
columns: (1fr,) * items.pos().len(),
column-gutter: 1em,
..items.pos(),
)
#columns[Item 1][Item 2][Item 3] // 3-column grid
// Mix named + variadic
#let mybox(..content, fill: white) = block(
fill: fill,
inset: 8pt,
..content.pos().join(),
)Common patterns
Theorem environment
#let theorem(name, body) = {
block(
stroke: (left: 2pt + blue),
inset: (left: 8pt, top: 4pt, bottom: 4pt),
)[
*Theorem (#name).* #body
]
}
#theorem("Pythagoras")[
In a right triangle, $a^2 + b^2 = c^2$.
]Custom note callout
#let note(body, kind: "info") = {
let colors = (
info: (rgb("#e3f2fd"), rgb("#1976d2")),
warning: (rgb("#fff8e1"), rgb("#f9a825")),
danger: (rgb("#ffebee"), rgb("#c62828")),
)
let (bg, fg) = colors.at(kind)
block(
fill: bg,
stroke: 1pt + fg,
inset: 8pt,
radius: 4pt,
body,
)
}
#note[Standard info note]
#note(kind: "warning")[Watch out!]
#note(kind: "danger")[Critical issue]Functions vs #set rules
- #set: changes default parameters globally.
#set text(size: 12pt)affects all text. - Functions: reusable wrappers you explicitly call.
#let big(body) = text(size: 16pt, body); use as#big[Hello].
Use #set when you want a default behavior. Use a function when you want explicit, callable reusable pieces.
Common mistakes
- Forgetting the
#prefix. Function calls in markup mode need#:#greet("World"), notgreet("World"). - Mixing content and value arguments. Use
[]for content,(value, value)for values. - No semicolons or commas at boundaries. Multiple arguments separated by commas; statements in a function body don't need semicolons.
- Default values for required args. Required args have no default; optional args have
name: default.
TypeTeX is a free in-browser Typst editor — define a function, call it, see the output instantly.
Try TypeTeX freeFrequently Asked Questions
Use #let with arguments: #let greet(name) = [Hello, #name!]. Then #greet("World") outputs 'Hello, World!'. Functions are first-class values — you can pass them as arguments, store them in variables, and return them from other functions.
#let x = 5 creates a variable. #let foo(arg) = ... creates a function. Both use #let. Functions are just variables that hold callable values. You can also write #let foo = (arg) => ... for an arrow-style function (anonymous function syntax).
Define with default values: #let highlight(content, color: red) = .... Call with named: #highlight("text", color: blue). Or positionally: #highlight("text", blue) — but named is clearer for readability.
Square brackets [] are used for content arguments — Typst's special syntax for passing markdown-style content to functions. #let alert(content) = block(fill: yellow, content). Then #alert[*Important* notice]. The [] is shorthand for an inline content block.
(arg1, arg2) is regular function call. content arguments inside are positional or named values. [content] is content-block argument — Typst-specific. You can mix: #function(arg, [content]). Conventionally, the LAST positional argument is often a content block, so [content] at the end is common.
Use ..args: #let row(..items) = grid(columns: items.pos().len(), ..items.pos()). The ..items captures all positional args into an array. Call with #row[A][B][C] to get a 3-column grid. Useful for table-like or list-like APIs.
#set changes default parameter values for an element type globally: #set text(size: 12pt) makes all text 12pt. Functions are reusable templates: #let mytext(body) = text(size: 12pt, body) lets you call #mytext[some text] explicitly. Use #set for global defaults; functions for explicit reusable wrappers.
Return value is the last expression in the function body. For content: #let foo() = [some content]. For computation: #let total(items) = items.fold(0, (a, b) => a + b). Multi-line: wrap in {} braces with the final expression as return value.
Define functions in helpers.typ. In main.typ: #import "helpers.typ": foo, bar. Now foo and bar are available. Or #import "helpers.typ": * for all. Common pattern for thesis projects with custom theorem environments, citations formatting, or styled blocks.