Harness-engineering ts-utility-types

TypeScript Utility Types

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/codex/ts-utility-types" ~/.claude/skills/intense-visions-harness-engineering-ts-utility-types-187024 && rm -rf "$T"
manifest: agents/skills/codex/ts-utility-types/SKILL.md
source content

TypeScript Utility Types

Apply built-in TypeScript utility types to transform and compose types without redundancy

When to Use

  • You need a variant of an existing type with some properties optional, required, or removed
  • You want to derive a type from a function's return value or parameter list without duplicating it
  • You need to build a lookup map type from a union of keys
  • You want to filter a union type to include or exclude specific members
  • You are building form types, API response shapes, or partial update payloads

Instructions

  1. Use
    Partial<T>
    for optional-update payloads where every field is optional.
  2. Use
    Required<T>
    to make every optional field mandatory (opposite of Partial).
  3. Use
    Pick<T, K>
    to create a type with only the listed keys from T.
  4. Use
    Omit<T, K>
    to create a type with all keys except the listed ones.
  5. Use
    Record<K, V>
    to define a mapping type — prefer over index signatures when keys are known.
  6. Use
    Exclude<T, U>
    to remove union members assignable to U from T.
  7. Use
    Extract<T, U>
    to keep only union members assignable to U.
  8. Use
    ReturnType<typeof fn>
    to derive the return type of a function without manually declaring it.
  9. Use
    Parameters<typeof fn>
    to derive the parameter tuple of a function.
  10. Chain utility types when needed:
    Partial<Pick<User, 'name' | 'email'>>
    .
interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'viewer' | 'editor';
  createdAt: Date;
}

// Partial update payload — all fields optional
type UserUpdate = Partial<Omit<User, 'id' | 'createdAt'>>;

// Public profile — only safe fields
type PublicUser = Pick<User, 'id' | 'name' | 'role'>;

// Role lookup map
type RoleConfig = Record<User['role'], { canWrite: boolean; canDelete: boolean }>;

// Exclude admin from public-facing role type
type PublicRole = Exclude<User['role'], 'admin'>; // 'viewer' | 'editor'

// Infer return type without coupling to implementation
async function fetchUser(id: string): Promise<User> {
  /* ... */ return {} as User;
}
type FetchUserResult = Awaited<ReturnType<typeof fetchUser>>; // User

// Infer parameters for wrapping/mocking
type FetchUserParams = Parameters<typeof fetchUser>; // [id: string]

Details

All utility types are implemented as generic conditional or mapped types in TypeScript's standard library (

lib.es5.d.ts
). Understanding their implementation helps you build custom variants when the built-ins don't cover your case.

Implementation anatomy

// Partial<T> implementation
type Partial<T> = { [P in keyof T]?: T[P] };

// Pick<T, K> implementation
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

// Exclude<T, U> implementation
type Exclude<T, U> = T extends U ? never : T;

// ReturnType<T> implementation
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

Omit
vs
Exclude

Omit<T, K>
operates on object types and removes properties.
Exclude<T, U>
operates on union types and removes members. They are not interchangeable.

Record
vs index signatures

Record<string, V>
and
{ [key: string]: V }
are equivalent for most purposes, but
Record<K, V>
with a union K creates a required entry for each union member — the index signature does not.

Composing utility types

Utility types compose via nesting. Deep transformations may require recursive types (TypeScript 4.1+) or a custom mapped type. For deeply partial types, the standard library's

Partial
only goes one level deep.

NonNullable<T>

Removes

null
and
undefined
from a type. Equivalent to
Exclude<T, null | undefined>
. Useful after null-safety guards.

ConstructorParameters<T>
and
InstanceType<T>

Less common but useful for class-based code:

ConstructorParameters
extracts the constructor's args,
InstanceType
extracts what
new T()
produces.

When to write custom utilities instead

When none of the built-ins express your transformation, write a mapped or conditional type. The built-ins are a starting point, not a ceiling.

Source

https://typescriptlang.org/docs/handbook/utility-types.html

Process

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. 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.