install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/ts-template-literal-types" ~/.claude/skills/intense-visions-harness-engineering-ts-template-literal-types && rm -rf "$T"
manifest:
agents/skills/claude-code/ts-template-literal-types/SKILL.mdsource content
TypeScript Template Literal Types
Construct precise string types using template literal syntax and string manipulation types
When to Use
- Creating type-safe string patterns (event names, CSS values, API routes)
- Generating getter/setter method names from property names
- Building type-safe routing or event systems
- Manipulating string literal types with Capitalize, Uppercase, Lowercase
Instructions
- Basic template literal type:
type EventName = `on${Capitalize<'click' | 'hover' | 'focus'>}`; // 'onClick' | 'onHover' | 'onFocus'
- Combine with union types — distributes across all combinations:
type Color = 'red' | 'blue' | 'green'; type Size = 'sm' | 'md' | 'lg'; type ClassName = `${Color}-${Size}`; // 'red-sm' | 'red-md' | 'red-lg' | 'blue-sm' | 'blue-md' | ...
- Type-safe event emitters:
type Events = { click: { x: number; y: number }; change: { value: string }; submit: { data: FormData }; }; type OnEvent = `on${Capitalize<keyof Events>}`; // 'onClick' | 'onChange' | 'onSubmit'
- String manipulation utility types:
type Upper = Uppercase<'hello'>; // 'HELLO' type Lower = Lowercase<'HELLO'>; // 'hello' type Cap = Capitalize<'hello'>; // 'Hello' type Uncap = Uncapitalize<'Hello'>; // 'hello'
- Generate property names from a type:
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]; }; type Setters<T> = { [K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void; }; type UserAccessors = Getters<{ name: string; age: number }>; // { getName: () => string; getAge: () => number }
- Pattern matching with
:infer
type ExtractRouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractRouteParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? Param : never; type Params = ExtractRouteParams<'/users/:userId/posts/:postId'>; // 'userId' | 'postId'
- Type-safe CSS values:
type CSSUnit = 'px' | 'em' | 'rem' | '%' | 'vh' | 'vw'; type CSSLength = `${number}${CSSUnit}`; function setWidth(width: CSSLength): void { /* ... */ } setWidth('100px'); // OK setWidth('2.5rem'); // OK setWidth('100'); // Error: not assignable to CSSLength
- Dot-notation path types:
type DotPath<T, Prefix extends string = ''> = { [K in keyof T & string]: T[K] extends object ? DotPath<T[K], `${Prefix}${K}.`> : `${Prefix}${K}`; }[keyof T & string]; type Paths = DotPath<{ user: { name: string; address: { city: string } } }>; // 'user.name' | 'user.address.city'
Details
Template literal types (TypeScript 4.1+) allow string types to be composed from other string literals, unions, and type-level transformations. They are the string equivalent of mapped types — they generate new types by iterating over string combinations.
Distribution: When a template literal contains union types, it produces the Cartesian product.
\${A | B}-${C | D}`produces'A-C' | 'A-D' | 'B-C' | 'B-D'`.
Intrinsic string manipulation types:
Uppercase<S>, Lowercase<S>, Capitalize<S>, Uncapitalize<S> are built-in compiler intrinsics — they work on any string literal type.
Pattern matching: Template literal types with
infer can extract parts of string types. This enables parsing route parameters, CSS values, and other structured strings at the type level.
Performance considerations:
- Large Cartesian products slow the compiler.
${100 values}-${100 values}`` creates 10,000 types\ - Recursive template literal types have a depth limit. Keep recursion shallow
- Avoid template literals in hot type positions (deeply nested generics)
Trade-offs:
- Precise string typing catches typos at compile time — but generates verbose union types in IDE tooltips
- Route parameter extraction is elegant — but error messages when a route does not match are cryptic
- Template literals distribute over unions automatically — this is powerful but can produce unexpectedly large types
Source
https://typescriptlang.org/docs/handbook/2/template-literal-types.html
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.