CtrlK
BlogDocsLog inGet started
Tessl Logo

typescript-advanced-type-system

Advanced TypeScript type-system mechanics — union and intersection types, conditional types with `infer`, mapped types, template literal types, generics and their constraints, index signatures, type assertions, and extracting types from other types (return types, array elements, promise results). Use when designing a complex generic, modeling a type that transforms based on another type, extracting a type from a function or structure with `infer`, or deciding between a type assertion and a real narrowing check.

71

Quality

87%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

TypeScript Type System

The type-level mechanics that everything else in this skill family builds on: unions, conditionals, mapped types, template literals, generics, and type-level extraction with infer.

Mindset

Model the problem in types before reaching for a runtime check — a type that makes an invalid combination unrepresentable is a compile-time guarantee, while a runtime check for the same thing only protects the paths that get exercised. Prefer deriving a type from another type (ReturnType<typeof fn>, a mapped type, a conditional extraction with infer) over hand-writing a parallel type that can drift out of sync with the thing it describes. When a conditional type distributes over a union unexpectedly, that is usually the type system doing exactly what it's told — wrap the checked type in a tuple ([T] extends [U]) to opt out of distribution rather than restructuring the type to dodge it. A type assertion (as) is a claim, not a check; only reach for one when you have already established the fact some other way (e.g. immediately after a runtime guard), never as a way to silence an error you haven't investigated.

When to Apply

Use this skill when:

  • Modeling a union or intersection type, including discriminated unions at the type-definition level
  • Writing a conditional type, especially one using infer to extract a nested type
  • Building a mapped type or remapping its keys with an as clause
  • Constructing a template literal type (e.g. typed route parameters)
  • Designing a generic function or type with meaningful constraints
  • Extracting a type from a function, array, promise, or constructor
  • Deciding whether a value needs an index signature or a fixed shape
  • Choosing between a type assertion and a real narrowing check

Use When

  • "How do I extract the return type / element type / awaited type from this?"
  • "How should I model this union or generic type?"
  • "How do I build a type that changes shape based on another type?"
  • "What's the difference between as and a type guard here?"

Scope

In Scope

  • Union, intersection, conditional, mapped, and template literal types.
  • Generics and their constraints.
  • Index signatures and type assertions.
  • Type-level extraction with infer (return types, array elements, promise values, tuple destructuring, constructor/instance types).

Out of Scope

  • Runtime narrowing and type guards (typeof, instanceof, custom predicates) — see the sibling typescript-type-guards skill, which also owns exhaustiveness checking.
  • Built-in utility types that wrap these mechanics for common cases (Partial, Pick, ReturnType as a ready-made utility) — see the sibling typescript-utility-types skill for the applied, ready-to-use versions.
  • Design patterns that use these mechanics structurally — see the sibling typescript-design-patterns skill.

When NOT to Use

Do not use this skill for a runtime check — narrowing a value at runtime with typeof/instanceof/a custom predicate belongs in typescript-type-guards. Do not use it as a substitute for tsc --noEmit; a type that looks correct in isolation can still fail to apply as expected against real call sites.

Quick Commands

Type Check

npx tsc --noEmit

Type Check Single Entry

npx tsc --noEmit src/index.ts

Anti-Patterns

NEVER silence a type error with an unchecked assertion instead of modeling the type correctly

WHY: an as assertion bypasses the compiler without a matching runtime guarantee; the error it silences almost always points at a type that needs to be modeled more precisely, not asserted away.

BAD:

const id = getValue() as string;

GOOD:

type Result = { kind: "ok"; value: string } | { kind: "error"; message: string };
function unwrap(result: Result): string {
  if (result.kind === "error") throw new Error(result.message);
  return result.value;
}

NEVER hand-write a type that duplicates what infer or a mapped type could derive

WHY: a hand-written parallel type drifts out of sync with the source it was copied from the first time either one changes.

BAD:

function getUser() { return { id: 1, name: "Alice" }; }
interface User { id: number; name: string; } // duplicates getUser's actual return shape

GOOD:

function getUser() { return { id: 1, name: "Alice" }; }
type User = ReturnType<typeof getUser>; // stays correct if getUser changes

NEVER leave a generic parameter unconstrained when the type only makes sense for a shape

WHY: an unconstrained <T> accepts anything, including values the type's own logic assumes won't appear.

BAD:

type PropType<T, K> = T extends { [P in K]: infer V } ? V : never; // K unconstrained

GOOD:

type PropType<T, K extends keyof T> = T extends { [P in K]: infer V } ? V : never;

References

FileCovers
references/unions-intersections.mdUnion and intersection types
references/conditional-types.mdConditional types, infer, distributive behavior
references/mapped-types.mdMapped types and key remapping mechanics
references/template-literal-types.mdTemplate literal types (e.g. typed route parameters)
references/generics.mdGeneric constraints and type parameters
references/index-signatures.mdIndex signatures and dynamic properties
references/type-assertions.mdas assertions and type compatibility
references/infer-extraction.mdExtracting return types, parameters, array elements, promise values, tuple elements, and instance/this types with infer
  • TypeScript Handbook: Conditional Types
  • TypeScript Handbook: Mapped Types
  • TypeScript Handbook: Template Literal Types
Repository
pantheon-org/tekhne
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.