Skip to content
Development
Skill

/meta-design-expressive-typescript

Readable TypeScript functions — orchestrators over pure helpers, named predicates and transforms, guard clauses, exhaustive unions. Load when writing or refactoring a function that mixes validation, transformation and assembly, or when deciding whether an expression should be

From plugin
skills
26200 skills

Claude Code

$ npx -y skills add agents-inc/skills --skill meta-design-expressive-typescript --agent claude-code

SKILL.md

meta-design-expressive-typescript.SKILL.md
name: meta-design-expressive-typescript
description: Readable TypeScript functions — orchestrators over pure helpers, named predicates and transforms, guard clauses, exhaustive unions. Load when writing or refactoring a function that mixes validation, transformation and assembly, or when deciding whether an expression should be extracted.

Expressive TypeScript Patterns

> **Quick Guide:** One test decides every change: can a reader follow the flow without simulating any part of it? Where they cannot, the part they would simulate gets a name, and the function becomes an orchestrator — guards, named calls, assembly — over small pure helpers; where they can, the code stays inline. Two compiler checks carry the shape: a `never` default fails compilation when a union grows past its `switch`, and `as const satisfies` checks a config without widening its literals.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — orchestrator before/after, named predicates, transforms and constants, guard clauses, exhaustive unions, async orchestrators, `as const satisfies`
  • [examples/data-transforms.md](examples/data-transforms.md) — grouping, counting, partitioning and indexing by name; when `pipe` helps and when it hurts
  • [reference.md](reference.md) — refactoring moves at a glance, and what each compiler check needs

---

<critical_requirements>

Before writing expressive TypeScript

**Write each orchestrator as guard clauses, then named calls, then the assembly of their results.** A reader learns what every step produces from its name; a transformation written inline has to be run in their head before the next line means anything.

**Extract what a reader would have to simulate, and leave what reads in one scan.** A name is the only thing extraction adds, so a helper whose name restates its single line adds a jump and nothing else.

**Name a function for the fact it establishes — `isContentAddition(line)`, not `startsWithPlusButNotTriplePlus(line)`.** A name that describes the mechanism has to change whenever the mechanism does, and tells the reader nothing the body did not.

**Pass every value an extracted helper reads as a parameter, or return the helper from a factory — `skills.filter(isRelevantTo(selection))`.** A helper that closes over its caller's locals cannot sit at the bottom of the file or be tested on its own, which is what extracting it was for.

**Use the plain array method where one call reads clearly, and an operation named for the concept where the manual version needs an accumulator.** `Object.groupBy(skills, (skill) => skill.category)` states what a loop over a mutable record makes the reader reconstruct; wrapping a single `.filter()` in a library call states nothing the method did not.

</critical_requirements>

---

**Auto-detection:** orchestrator function, two-tier function, extract function, named predicate, named transform, guard clause, early return, arrow anti-pattern, nested if/else, discriminated union, exhaustive switch, `never` default, `as const satisfies`, sequential await, `Promise.all`, `Object.groupBy`, `pipe`, readability refactor, mental simulation

**Applies to:**

  • Splitting a function that validates, transforms and assembles into an orchestrator over pure helpers
  • Deciding whether an expression earns a name or stays inline
  • Flattening nested conditionals into guard clauses
  • Modelling a fixed set of states so the compiler checks every handler
  • Typing static configuration so its shape is checked and its literals kept
  • Ordering the awaits in an async orchestrator
  • Choosing between a plain array method, an operation named for the concept, and `pipe`
  • Reviewing code for blocks a reader would have to simulate

**Handled elsewhere:**

  • Failure as a return value — encoding a function's errors in its return type is a decision of its own; this skill shapes the code around whatever a function returns.
  • Where a collection operation comes from — which native method or library supplies `groupBy` or `partition`, and which runtimes have it, is settled by whatever owns the project's utilities; this skill asks only that the call site name the operation.
  • Formatting, import order and file naming — the project's formatter and lint configuration settle those.

---

<philosophy>

Expressive TypeScript is readability-first, practical functional programming. Two ideas carry it:

1. **Orchestrators read like pseudocode** — guards, named calls, assembly. Side effects belong here, where the reader can see them. 2. **Helpers do one thing and are pure** — each named for its purpose, each testable with nothing but its arguments.

What it is not: category theory (monads, functors, effect systems); composition with no named data, such as `compose(map(prop("name")), filter(isActive))` — passing a named function to `filter` is fine, a chain with no visible argument is not; or extraction for its own sake. Three similar lines beat a premature abstraction.

</philosophy>

---

<decision_framework>

Extract, or leave inline

Does a reader have to simulate this block to know what it produces?
├─ NO → Leave it inline. A one-expression lambda reading a named field is already named.
└─ YES → Does the same logic appear in two or more places?
    ├─ YES → Extract once, and call it from each.
    └─ NO → Would a name say something the expression does not?
        ├─ YES → Extract. The name is the documentation.
        └─ NO → Leave it. selectedIds.has(item.id) needs no isItemSelected.

Orchestrator, or leave the function alone

A function earns the two-tier shape when it mixes concerns — validating, transforming, assembling — or when it runs past about fifteen lines in clear steps. Past that length with no clear steps, split it by responsibility first; under it, with one concern, leave it alone. A hot path where a profile shows the extra calls matter is the one place readability yields.

Array method, named operation, or `pipe`

One map, filter,
Read more
@agents-inc
Ships withskills

The official skills marketplace for Agents Inc. 230+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Stars on GitHub

Momentum

stars in total
26
Star history of agents-inc/skills on GitHub, a chart by star-history.com

Other skills on skills.

ai-infrastructure-litellm

ai-infrastructure-lite…

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…

@agents-inc@agents-incInstall Skill
ai-infrastructure-modal

ai-infrastructure-moda…

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…

@agents-inc@agents-incInstall Skill
ai-infrastructure-ollama

ai-infrastructure-olla…

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…

@agents-inc@agents-incInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about meta-design-expressive-typescript.

Which coding agents can use meta-design-expressive-typescript?
meta-design-expressive-typescript installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.