Official agent skill

AST Visitor Pattern for Unions

by prisma in prisma/orm

Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants.

OfficialApache-2.0Auto-check passedDevelopment

Install AST Visitor Pattern for Unions

skills CLI
$ npx skills add prisma/orm --skill ast-visitor-pattern -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install prisma/orm ast-visitor-pattern --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/prisma/orm.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills-contrib/ast-visitor-pattern .claude/skills/ast-visitor-pattern && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ast-visitor-pattern
GitHub stars
48k
Token cost
~830 tokens
SKILL.md length
176 words
Files
1
Skills in repo
20
Repo updated
First seen
Licence
Apache-2.0

At a glance

Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants.

  • Creating a new set of variants that several functions will switch over
  • SKILL.md covers Structure, Consuming, Always construct instances,… and When NOT to use, plus 1 more section
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Refactoring a union type whose switch statements have spread across files

What it does

When a discriminated union has three or more variants and two or more places that branch on it, such as renderers, serializers or classifiers, the plain union and switch give way to frozen subclasses with a visitor interface. The payoff is that adding a variant becomes a compiler error in every consumer, instead of a silent gap. The structure has an unexported abstract base, concrete node classes, the union type and a visitor interface.

Consumers write one visitor object per concern. The skill insists on building real instances, such as `new BarNode('x')`, never frozen object literals, because a literal has no prototype: `instanceof` fails, `accept()` is missing and a shallow copy strips the type. It also lists when not to use the pattern: a single dispatch site, or fewer than three variants with no expected growth. Examples point to Prisma's Mongo query AST.

When your agent uses it

  • Creating a new set of variants that several functions will switch over
  • Refactoring a union type whose switch statements have spread across files
  • Reviewing factories that return frozen object literals instead of class instances

Example prompts

  • “Refactor the Command union in src/commands.ts into visitor-based classes, since three modules switch on it.”
  • “Add a new IR node type and make sure every consumer fails to compile until it handles it.”
  • “Check our node factories for frozen literals that would break instanceof checks.”

Requirements

  • A TypeScript codebase

What it can do on your machine

Read from SKILL.md and the folder at commit 095af7a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

AST Visitor Pattern for Unions loads about 830 tokens when it runs. Until then it costs about 79 tokens; SKILL.md has 176 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~79
When it runs · the whole SKILL.md, loaded when a task matches
~830

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from prisma/orm at commit 095af7a, republished under its Apache-2.0 licence (© prisma). 176 words, ~830 tokens.

Download SKILL.mdSave it as .claude/skills/ast-visitor-pattern/SKILL.md (or your agent's skills folder).
name
ast-visitor-pattern
description
Use the frozen-class/visitor pattern for discriminated unions that have multiple dispatch sites. Use when creating a new set of variants (commands, IR nodes, factory calls) that will be switched over in 2+ places, or when refactoring an existing union type that has grown multiple switch sites.

AST Class/Visitor Pattern

When a discriminated union has 3+ variants and 2+ dispatch sites (renderers, serializers, classifiers, etc.), replace plain union + switch with frozen subclasses and a visitor interface. This makes adding a new variant a compiler error at every consumer, instead of a silent omission.

Structure

Four pieces, usually in one file — the Mongo DDL set below spreads them over three:

typescript
// 1. Abstract base (not exported — consumers use the union type)
abstract class FooNode {
  abstract readonly kind: string;
  abstract accept<R>(visitor: FooVisitor<R>): R;
  protected freeze(): void { Object.freeze(this); }
}

// 2. Visitor interface
export interface FooVisitor<R> {
  bar(node: BarNode): R;
  baz(node: BazNode): R;
}

// 3. Concrete subclasses — readonly fields, freeze() in constructor
export class BarNode extends FooNode {
  readonly kind = 'bar' as const;
  readonly value: string;
  constructor(value: string) {
    super();
    this.value = value;
    this.freeze();
  }
  accept<R>(visitor: FooVisitor<R>): R { return visitor.bar(this); }
}

export class BazNode extends FooNode {
  readonly kind = 'baz' as const;
  readonly count: number;
  constructor(count: number) {
    super();
    this.count = count;
    this.freeze();
  }
  accept<R>(visitor: FooVisitor<R>): R { return visitor.baz(this); }
}

// 4. Union type
export type Foo = BarNode | BazNode;

Consuming

Define a visitor object (or class) per concern:

typescript
const renderVisitor: FooVisitor<string> = {
  bar(node) { return node.value; },
  baz(node) { return String(node.count); },
};

function render(node: Foo): string {
  return node.accept(renderVisitor);
}

Always construct instances, never frozen object literals

This holds everywhere a node is built — tests and production construction surfaces (contract-free factories, builders). A factory must return new BarNode(...), never Object.freeze({ kind: 'bar', value: 'x' }). A frozen plain object has no prototype, so instanceof fails, accept() is missing, and a downstream shallow-copy ({ ...node }) silently strips the type back to an anonymous bag; constructor-time invariants are skipped too.

typescript
// ✅
const call = new BarNode('x');
export function bar(value: string): BarNode { return new BarNode(value); }

// ❌
const call: Foo = { kind: 'bar', value: 'x' };
export function bar(value: string): Foo { return Object.freeze({ kind: 'bar', value }); }

When NOT to use

  • Single dispatch site → plain union + switch is simpler
  • Fewer than 3 variants with no expected growth → not worth the boilerplate

Codebase examples

  • MongoAstNode base — packages/2-mongo-family/4-query/query-ast/src/ast-node.ts
  • MongoDdlCommandVisitor interface — packages/2-mongo-family/4-query/query-ast/src/ddl-visitors.ts
  • Concrete DDL commands and their union — packages/2-mongo-family/4-query/query-ast/src/ddl-commands.ts

© prisma, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills-contrib/ast-visitor-pattern of prisma/orm.

Open the folder on GitHubat commit 095af7a

Compare with similar skills

AST Visitor Pattern for Unions next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

AST Visitor Pattern for Unions compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
AST Visitor Pattern for Unions this skillprisma/orm48k—~830Automated safety check: PassApache-2.0
RTK Rust Design Patternsrtk-ai/rtk83k—~1.9kAutomated safety check: PassApache-2.0
Vue Best Practicesoyjt/uniapp-vue3-template6273 repos~667Automated safety check: PassMIT
Typed Dependencies with fp-go EffectIBM/fp-go2k—~4.3kAutomated safety check: PassApache-2.0
Effect TSmattiacerutti/supernova187—~2.8kAutomated safety check: PassMIT
Typescript React ReviewerSuFxGIT/scoutarr114—~1.7kAutomated safety check: PassNone

Similar skills

  • Describes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill.

    83k GitHub stars~1.9k tokensUpdated today
    DevelopmentAuto-check passed
  • Vue Best Practices

    oyjt/uniapp-vue3-template

    Vue 3 and Vue.js best practices for TypeScript, vue-tsc, and Volar.

    627 GitHub starsUsed in 3 repos~667 tokens
    DevelopmentAuto-check passed
  • Teaches an agent to write fp-go v2 services with the Effect type, carrying dependencies in its type parameter instead of in context.Context or parameters.

    2k GitHub stars~4.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Effect TS

    mattiacerutti/supernova

    Write idiomatic Effect v4 TypeScript following official best practices from effect-solutions and the Effect source.

    187 GitHub stars~2.8k tokensUpdated today
    DevelopmentAuto-check passed
  • Expert code reviewer for TypeScript + React 19 applications.

    114 GitHub stars~1.7k tokensUpdated 6 mo ago
    DevelopmentAuto-check passed
  • Typescript Best Practices

    jwynia/agent-skills

    Guide AI agents through TypeScript coding best practices including type safety, error handling, code organization, and architecture patterns.

    165 GitHub stars~2.5k tokensUpdated 7 mo ago
    DevelopmentAuto-check passed

More from prisma/orm

All 20 skills in this repo
  • Official

    Runs a loop on a GitHub pull request: fetch review state, triage comments into actions, implement them and resolve threads, repeating until nothing actionable is left.

    48k GitHub stars~2.2k tokensUpdated yesterday
    Auto-check passed
  • Official

    Fetches a pull request's canonical review state as JSON, validates it, and renders markdown, a text summary and triage target files from it using bundled scripts.

    48k GitHub stars~767 tokensUpdated yesterday
    Auto-check passed
  • Official

    Implements triaged pull request review actions, commits focused fixes, posts status replies on GitHub and resolves the threads.

    48k GitHub stars~1.7k tokensUpdated yesterday
    Auto-check passed
  • Official

    Runs the triage step of the review-framework loop: reads fetched PR review state, builds `review-actions.json`, validates it and renders `review-actions.md`.

    48k GitHub stars~995 tokensUpdated yesterday
    Auto-check passed
  • Official

    Guides an outside contributor through opening a prisma/orm pull request from a fork that follows CONTRIBUTING.md and passes review on the first round.

    48k GitHub stars~2.3k tokensUpdated yesterday
    Auto-check passed
  • Official

    Creates a GitHub pull request for the Prisma repo with a Linear-ticket-prefixed title and a decision-led narrative description, inferring the ticket from context.

    48k GitHub stars~4.6k tokensUpdated yesterday
    Auto-check passed

Works with

Categories

Questions about AST Visitor Pattern for Unions

What does AST Visitor Pattern for Unions do?

Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants. When a discriminated union has three or more variants and two or more places that branch on it, such as renderers, serializers or classifiers, the plain union and switch give way to frozen subclasses with a visitor interface. The payoff is that adding a variant becomes a compiler error in every consumer, instead of a silent gap.

When should I use AST Visitor Pattern for Unions?

AST Visitor Pattern for Unions fits situations like: creating a new set of variants that several functions will switch over; refactoring a union type whose switch statements have spread across files; reviewing factories that return frozen object literals instead of class instances.

How do I install AST Visitor Pattern for Unions in Claude Code?

Run `npx skills add prisma/orm --skill ast-visitor-pattern -a claude-code`. Or copy the skill folder (skills-contrib/ast-visitor-pattern in prisma/orm) into .claude/skills/ast-visitor-pattern in your project. Claude Code loads it when a task matches its description.

How do I install AST Visitor Pattern for Unions in Codex?

Run `npx skills add prisma/orm --skill ast-visitor-pattern -a codex`. Or copy the skill folder (skills-contrib/ast-visitor-pattern in prisma/orm) into .agents/skills/ast-visitor-pattern in your project. Codex loads it when a task matches its description.

Can I use AST Visitor Pattern for Unions in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add prisma/orm --skill ast-visitor-pattern -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ast-visitor-pattern, .gemini/skills/ast-visitor-pattern, .github/skills/ast-visitor-pattern and .opencode/skills/ast-visitor-pattern in your project.

What does AST Visitor Pattern for Unions need to run?

SKILL.md names no scripts, command-line tools or credentials: AST Visitor Pattern for Unions is instructions for the agent only. Our summary lists: A TypeScript codebase.

Does AST Visitor Pattern for Unions access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is AST Visitor Pattern for Unions safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does AST Visitor Pattern for Unions use?

AST Visitor Pattern for Unions is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does AST Visitor Pattern for Unions use?

About 830 tokens (SKILL.md is roughly 3.3k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to AST Visitor Pattern for Unions?

Skills that share tags, products or a category with AST Visitor Pattern for Unions: RTK Rust Design Patterns (rtk-ai/rtk, 83k stars), Vue Best Practices (oyjt/uniapp-vue3-template, 627 stars), Typed Dependencies with fp-go Effect (IBM/fp-go, 2k stars) and Effect TS (mattiacerutti/supernova, 187 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains AST Visitor Pattern for Unions?

prisma (a GitHub organization, an official publisher) maintains it in prisma/orm, which has 47,701 GitHub stars. The repository holds 20 skills in this directory. The repository was last updated on October 6, 2026.

Source: prisma/orm on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.