AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Types First Guards

skill-mateonunez-skills-types-first-guards · by mateonunez

Use strict TypeScript patterns — discriminated unions for domain concepts, exhaustive checks, nominal typing where needed. Use when writing domain logic that deals with user IDs, order IDs, or other concepts that should not be interchangeable even if their runtime type is the same.

No reviews yet
0 installs
35 views
0.0% view→install

Install

$ agentstack add skill-mateonunez-skills-types-first-guards

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-mateonunez-skills-types-first-guards)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Types First Guards? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Types First Guards

> "If the types don't catch the error, the types are lying."

Philosophy

I use TypeScript as a guardrail against the entire class of "oops, I passed the wrong ID" bugs. The type system should make certain mistakes impossible at compile time, not catch them at runtime.

The Pattern

Nominal domain types for anything that should never be confused at the type level, even if runtime representation is identical:

type UserId = string & { readonly __brand: 'UserId' };
const userId = (id: string): UserId => id as UserId;

type OrgId = string & { readonly __brand: 'OrgId' };
const orgId = (id: string): OrgId => id as OrgId;

// Now this type-checks:
const user = await fetchUser(userId('42'));
const org = await fetchOrg(orgId('42'));

// But this does NOT:
const badUser = await fetchUser(orgId('42')); // ✗ Type error

No reflexive runtime checks. The type system prevents the mistake in the first place.

Discriminated Unions for Multi-State Data

For domain concepts that have distinct states or variants, use __type discriminator unions:

type Order =
  | { __type: 'pending'; id: OrderId; items: OrderItem[] }
  | { __type: 'confirmed'; id: OrderId; items: OrderItem[]; confirmedAt: Date }
  | { __type: 'shipped'; id: OrderId; items: OrderItem[]; trackingNumber: string }
  | { __type: 'cancelled'; id: OrderId; reason: string };

function handleOrder(order: Order) {
  switch (order.__type) {
    case 'pending': return processPayment(order);
    case 'confirmed': return scheduleShipment(order);
    case 'shipped': return notifyCustomer(order);
    case 'cancelled': return refund(order);
  }
  // ✓ TypeScript enforces exhaustiveness
}

The compiler forces you to handle every case. Refactoring adds a state? The compiler catches you.

When Nominal Types Help Most

  • IDs that should never be mixed: UserId, OrgId, ProjectId, OrderId. Use this pattern aggressively.
  • Concepts from your domain glossary (in CONTEXT.md) that have different meanings even if they're structurally the same string/number.
  • Auth boundaries: SessionToken vs RefreshToken vs ApiKey — different tokens, different lifespans, different threat models.

Do NOT do this for every string. Use it for semantic differences, not syntactic ones.

Anti-Patterns

  • unknown in business logic. Unknown is "I don't know the type." If you don't know, you're missing domain understanding. Dig until you do.
  • as any to make TypeScript shut up. This is a sign the types don't reflect reality. Fix the types, not the code.
  • Discriminated unions without exhaustiveness checking. If you write a switch on __type without handling all cases, the type system should reject it. Ensure you're using never in unreachable branches to force exhaustiveness.
function handleOrder(order: Order) {
  switch (order.__type) {
    case 'pending': return processPayment(order);
    case 'confirmed': return scheduleShipment(order);
    // ✗ Missing 'shipped' and 'cancelled' cases
    default: return never; // Type error: can't assign Order to never
  }
}
  • Mixing domain and primitive types. Never do const userId: string when you have a UserId type. Always use the nominal type.
  • Type assertions on untrusted data at boundaries. JSON.parse(userInput) as Order is a lie. Validate first, then type-assert.

Phases

  1. Identify domain concepts — what are the distinct semantic types in your domain? (from CONTEXT.md if it exists)
  2. Create nominal types or discriminated unions for each
  3. Enforce at boundaries — HTTP handlers, DB queries, external API calls. Validate untrusted data, then assert types.
  4. Use in business logic — pass these types through your service layer so mistakes are caught early
  5. Verify exhaustiveness — switch statements on discriminated unions should have type-checker enforcement via never in unreachable code

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.