Version-gated language features
verikt uses a feature matrix to generate version-appropriate code. Instead of targeting the lowest common denominator, templates use feature flags to emit modern APIs when the target language version supports them.
How It Works
Section titled “How It Works”- Detect version — verikt reads the language version from your project (language-specific, see below)
- Resolve features — the detected version is compared against
features.yaml, producing a boolean map - Inject into templates — templates access features via
{{if .Features.<name>}}...{{end}}
Language-specific version detection
Section titled “Language-specific version detection”How verikt detects the runtime version depends on the language:
- Go — runs
go env GOVERSION, or accepts an override via--set GoVersion=X.XX - TypeScript — runs
node --version, or accepts an override via--set NodeVersion=XX
Go Feature Matrix
Section titled “Go Feature Matrix”Each feature maps to the minimum Go version that introduced it. If your detected version is >= the since version, the feature is enabled.
| Feature | Description | Since |
|---|---|---|
slices_package | stdlib slices package (slices.SortFunc, slices.Contains) | 1.21 |
log_slog | stdlib structured logging (log/slog) | 1.21 |
maps_package | stdlib maps package | 1.21 |
range_over_int | for i := range n syntax | 1.22 |
range_over_func | for x := range func syntax (iterators) | 1.23 |
os_root | os.Root/os.OpenRoot for kernel-level path safety | 1.24 |
weak_pointers | weak package for weak pointers | 1.24 |
os_root_fs | os.Root implements fs.FS interface | 1.25 |
synctest | testing/synctest for concurrent test control | 1.25 |
generic_type_aliases | Fully generic type aliases | 1.25 |
Template Usage
Section titled “Template Usage”Templates use the .Features map to conditionally emit code:
{{if .Features.os_root}}root, err := os.OpenRoot(dir){{else}}f, err := os.Open(filepath.Join(dir, name)){{end}}{{if .Features.log_slog}}import "log/slog"{{else}}import "log"{{end}}features.yaml Format
Section titled “features.yaml Format”The feature matrix is a YAML file with a single features list:
features: - name: slices_package description: "stdlib slices package (slices.SortFunc, slices.Contains)" since: "1.21"| Field | Type | Description |
|---|---|---|
name | string | Identifier used in templates as .Features.<name> |
description | string | Human-readable explanation of the feature |
since | string | Minimum version that supports this feature |
TypeScript / Node.js Feature Matrix
Section titled “TypeScript / Node.js Feature Matrix”Node.js versions gate TypeScript-specific template behavior. The default Node version is 22 (current Active LTS). Override with --set NodeVersion=24.
| Feature | Description | Since |
|---|---|---|
native_ts | Stable native TypeScript (--strip-types enabled by default) — drops tsx dependency, uses node --watch | 24 |
es2024 | ES2024 target support (Object.groupBy, Promise.withResolvers, ArrayBuffer.transfer) | 24 |
What changes by Node version:
| Template concern | Node 20 | Node 22 (default) | Node 24 |
|---|---|---|---|
tsconfig.json target | ES2023 | ES2023 | ES2024 |
| Dev server | tsx watch | tsx watch | node --watch (native) |
tsx dependency | Required | Required | Dropped |
| Dockerfile base | node:20-alpine | node:22-alpine | node:24-alpine |
@types/node | ^20 | ^22 | ^24 |
Adding Features
Section titled “Adding Features”When a new Go or Node.js version ships with relevant changes:
- Add an entry to the provider’s
features.yaml - Update any templates that should use the new feature with
{{if .Features.<name>}} - Optionally add
conditionalrules in capability manifests for file-level gating (see verikt.yaml reference)
No changes to the feature resolver are needed — it reads features.yaml dynamically.