type-level-error-messages

Implements branded template-literal types that turn TypeScript constraint errors into readable messages.

4.8k|376|Updated Mar 16, 2023
One-click install
npx skills add https://github.com/EpicenterHQ/epicenter --skill type-level-error-messages
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: type-level-error-messages
Source: https://github.com/EpicenterHQ/epicenter/tree/main/.agents/skills/type-level-error-messages
Command: npx skills add https://github.com/EpicenterHQ/epicenter --skill type-level-error-messages

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

TypeScript's default error output for invalid literal keys or string shapes is cryptic (e.g. "not assignable to type 'never'"), giving library authors no way to point consumers at the exact offending value. This Skill provides a pattern for making compile-time errors read as plain English sentences.

Core Features & Use Cases

  • Branded template-literal error types: Encode the full error message in the type itself, so TS surfaces it at the exact bad property.
  • Recursive template-literal predicates: Validate string shapes like snake_case, kebab-case, or semver at the type level where regex-based tools fall back to string.
  • Paired runtime validation: Combine the compile-time check with a regex guard inside the helper function to catch dynamic keys and as casts.
  • Use Case: When building a defineActions helper that only accepts snake_case keys, a consumer writing tabs.close sees Type 'Action' is not assignable to type 'Invalid action key "tabs.close", must be snake_case ASCII...' instead of an opaque assignability failure.

Quick Start

Ask the AI to add a type-level snake_case constraint with a readable branded error message to a helper function like defineActions, following this Skill's pattern.

Frequently Asked Questions about type-level-error-messages

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I make TypeScript error messages readable for invalid keys?

Use a branded template-literal type as the error branch of a mapped type. When the predicate fails, the property's expected type becomes the message string itself, so TypeScript prints it as an English sentence pointing at the bad key.

How to validate snake_case string keys at the TypeScript type level?

Write a recursive template-literal predicate that pattern-matches the first character against a lowercase union and walks the rest against allowed word characters. Character-class patterns like [a-z] cannot be handled by arkregex, which falls back to string.

Why append a zero-width space to a TypeScript error message type?

The U+200B suffix brands the message so it is structurally distinct from any plain string a user could type. This keeps autocomplete from suggesting the error text and prevents other string-narrowing machinery from accidentally matching it.

Does a type-level check replace runtime validation in TypeScript?

No. Compile-time checks are bypassed by Object.fromEntries widening, as casts, and calls from plain JavaScript files. Pair the type predicate with a regex test inside the helper that throws on invalid keys at runtime.

Why does my mapped-type constraint reject every key in TypeScript?

If TypeScript infers T as Record<string, V>, keyof T becomes string and the predicate evaluates to false for all keys. Rely on homomorphic mapped-type inference over the argument's literal keys instead of a wide explicit T.