thebushidocollective/han/typescript-utility-types

Claude Code and agent skill by thebushidocollective/han

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when typeScript utility types, mapped types, and advanced type manipulation. Use when creating flexible, type-safe TypeScript code.

Install

npx vskill@latest install thebushidocollective/han/typescript-utility-types

SKILL.md

TypeScript Utility Types

Master TypeScript's powerful type system including built-in utility types, mapped types, conditional types, and advanced type manipulation techniques for creating flexible, type-safe code.

Built-in Utility Types

Partial and Required
typescript
interface User {
id: string;
name: string;
email: string;
age: number;
}
// Partial makes all properties optional
type PartialUser = Partial<User>;
// { id?: string; name?: string; email?: string; age?: number; }
function updateUser(id: string, updates: Partial<User>): User {
const existingUser = getUser(id);
return { ...existingUser, ...updates };
}
updateUser('123', { name: 'John' }); // Valid
updateUser('123', { age: 30 }); // Valid
// Required makes all properties required
interface OptionalConfig {
host?: string;
port?: number;
timeout?: number;
}
type RequiredConfig = Required<OptionalConfig>;
// { host: string; port: number; timeout: number; }
function validateConfig(config: Required<OptionalConfig>): boolean {
return config.host.length > 0 && config.port > 0;
}
Pick and Omit
typescript
interface Article {
id: string;
title: string;
content: string;
author: string;
createdAt: Date;
updatedAt: Date;
views: number;
}
// Pick selects specific properties
type ArticlePreview = Pick<Article, 'id' | 'title' | 'author'>;
// { id: string; title: string; author: string; }
function displayPreview(article: ArticlePreview): void {
console.log(`${article.title} by ${article.author}`);
}
// Omit removes specific properties
type ArticleWithoutDates = Omit<Article, 'createdAt' | 'updatedAt'>;
// { id: string; title: string; content: string; author: string; views: number; }
// Combining Pick and Omit
type ArticleMetadata = Pick<Article, 'id' | 'author' | 'createdAt'>;
type ArticleData = Omit<Article, 'id' | 'createdAt' | 'updatedAt'>;
Readonly and Record
typescript
// Readonly makes all properties readonly
type ReadonlyUser = Readonly<User>;
const user: ReadonlyUser = {
id: '1',
name: 'John',
email: 'john@example.com',
age: 30,
};
// user.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property
// Deep readonly for nested objects
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object
? DeepReadonly<T[P]>
: T[P];
};
// Record creates an object type with specific keys and value type
type UserRole = 'admin' | 'editor' | 'viewer';
type RolePermissions = Record<UserRole, string[]>;
// { admin: string[]; editor: string[]; viewer: string[]; }
const permissions: RolePermissions = {
admin: ['read', 'write', 'delete'],
editor: ['read', 'write'],
viewer: ['read'],
};
// Record with complex types
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type RouteHandler = (req: Request) => Response;
type RouteHandlers = Record<HttpMethod, RouteHandler>;
Extract and Exclude
typescript
type Status = 'pending' | 'approved' | 'rejected' | 'cancelled';
// Extract types that are assignable to a condition
type CompletedStatus = Extract<Status, 'approved' | 'rejected'>;
// 'approved' | 'rejected'
// Exclude types that are assignable to a condition
type ActiveStatus = Exclude<Status, 'approved' | 'rejected' | 'cancelled'>;
// 'pending'
// Practical example
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number }
| { kind: 'rectangle'; width: number; height: number };
type CircularShape = Extract<Shape, { kind: 'circle' }>;
// { kind: 'circle'; radius: number }
type NonCircularShape = Exclude<Shape, { kind: 'circle' }>;
// { kind: 'square'; side: number } | { kind: 'rectangle'; width: number; height: number }
ReturnType and Parameters
typescript
function createUser(name: string, age: number): User {
return {
id: generateId(),
name,
age,
email: `${name.toLowerCase()}@example.com`,
};
}
// ReturnType extracts the return type of a function
type UserFromFunction = ReturnType<typeof createUser>;
// User
// Parameters extracts parameter types as a tuple
type CreateUserParams = Parameters<typeof createUser>;
// [name: string, age: number]
// Using with generic functions
function processData<T>(data: T[]): { count: number; items: T[] } {
return { count: data.length, items: data };
}
type ProcessResult = ReturnType<typeof processData<User>>;
// { count: number; items: User[] }

Mapped Types

Basic Mapped Types
typescript
// Create a type where all properties are boolean
type Flags<T> = {
[P in keyof T]: boolean;
};
type UserFlags = Flags<User>;
// { id: boolean; name: boolean; email: boolean; age: boolean; }
// Create a type where all properties are nullable
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
type NullableUser = Nullable<User>;
// { id: string | null; name: string | null; email: string | null; age: number | null; }
// Create a type where all properties are functions
type Getters<T> = {
[P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};
type UserGetters = Getters<User>;
// { getId: () => string; getName: () => string; getEmail: () => string; getAge: () => number; }
Mapped Type Modifiers
typescript
// Remove readonly modifier
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
interface ReadonlyPerson {
readonly name: string;
readonly age: number;
}
type MutablePerson = Mutable<ReadonlyPerson>;
// { name: string; age: number; }
// Remove optional modifier
type Concrete<T> = {
[P in keyof T]-?: T[P];
};
interface OptionalUser {
name?: string;
age?: number;
}
type ConcreteUser = Concrete<OptionalUser>;
// { name: string; age: number; }
// Add optional modifier
type Optional<T> = {
[P in keyof T]+?: T[P];
};
Advanced Mapped Types
typescript
// Transform property types
type Promisify<T> = {
[P in keyof T]: Promise<T[P]>;
};
type AsyncUser = Promisify<User>;
// { id: Promise<string>; name: Promise<string>; email: Promise<string>; age: Promise<number>; }
// Wrap values in objects
type Boxed<T> = {
[P in keyof T]: { value: T[P] };
};
type BoxedUser = Boxed<User>;
// { id: { value: string }; name: { value: string }; ... }
// Create proxy type
type Proxy<T> = {
get(): T;
set(value: T): void;
};
type ProxiedProperties<T> = {
[P in keyof T]: Proxy<T[P]>;
};

Conditional Types

Basic Conditional Types
typescript
// T extends U ? X : Y
type IsString<T> = T extends string ? true : false;
type Test1 = IsString<string>; // true
type Test2 = IsString<number>; // false
// Nested conditionals
type TypeName<T> =
T extends string ? 'string' :
T extends number ? 'number' :
T extends boolean ? 'boolean' :
T extends undefined ? 'undefined' :
T extends Function ? 'function' :
'object';
type T0 = TypeName<string>; // 'string'
type T1 = TypeName<number>; // 'number'
type T2 = TypeName<() => void>; // 'function'
Distributive Conditional Types
typescript
// Conditional types distribute over union types
type ToArray<T> = T extends any ? T[] : never;
type StrOrNumArray = ToArray<string | number>;
// string[] | number[] (not (string | number)[])
// Non-distributive version
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
type StrOrNumArrayNonDist = ToArrayNonDist<string | number>;
// (string | number)[]
// Filter out null and undefined
type NonNullable<T> = T extends null | undefined ? never : T;
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>; // string
Inferring Types with infer
typescript
// Infer return type
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function example(): { x: number } {
return { x: 42 };
}
type ExampleReturn = GetReturnType<typeof example>;
// { x: number }
// Infer array element type
type Flatten<T> = T extends Array<infer U> ? U : T;
type Str = Flatten<string[]>; // string
type Num = Flatten<number>; // number
// Infer Promise type
type Awaited<T> = T extends Promise<infer U> ? U : T;
type PromiseString = Awaited<Promise<string>>; // string
type RegularString = Awaited<string>; // string
// Multiple infer usage
type GetFirstArg<T> = T extends (first: infer F, ...args: any[]) => any
? F
: never;
function multi(a: string, b: number, c: boolean): void {}
type FirstArgType = GetFirstArg<typeof multi>; // string

Template Literal Types

Basic Template Literals
typescript
type World = 'world';
type Greeting = `hello ${World}`; // 'hello world'
// With unions
type Color = 'red' | 'blue' | 'green';
type Quantity = 'one' | 'two';
type ColoredQuantity = `${Quantity} ${Color}`;
// 'one red' | 'one blue' | 'one green' | 'two red' | 'two blue' | 'two green'
// Event names
type EventName = 'click' | 'focus' | 'blur';
type EventHandler = `on${Capitalize<EventName>}`;
// 'onClick' | 'onFocus' | 'onBlur'
String Manipulation Types
typescript
// Built-in string manipulation types
type UppercaseGreeting = Uppercase<'hello'>; // 'HELLO'
type LowercaseGreeting = Lowercase<'HELLO'>; // 'hello'
type CapitalizedGreeting = Capitalize<'hello'>; // 'Hello'
type UncapitalizedGreeting = Uncapitalize<'Hello'>; // 'hello'
// Combining with template literals
type GetterName<T extends string> = `get${Capitalize<T>}`;
type SetterName<T extends string> = `set${Capitalize<T>}`;
type UserNameGetter = GetterName<'name'>; // 'getName'
type UserNameSetter = SetterName<'name'>; // 'setName'
// Generate accessor methods
type Accessors<T> = {
[K in keyof T as GetterName<string & K>]: () => T[K];
} & {
[K in keyof T as SetterName<string & K>]: (value: T[K]) => void;
};
type UserAccessors = Accessors<User>;
// { getName: () => string; setName: (value: string) => void; ... }
Pattern Matching with Template Literals
typescript
// Extract parts from string patterns
type ExtractRouteParams<T extends string> =
T extends `${infer Start}/:${infer Param}/${infer Rest}`
? { [K in Param | keyof ExtractRouteParams<`/${Rest}`>]: string }
: T extends `${infer Start}/:${infer Param}`
? { [K in Param]: string }
: {};
type Route1 = ExtractRouteParams<'/users/:userId/posts/:postId'>;
// { userId: string; postId: string; }
type Route2 = ExtractRouteParams<'/posts/:id'>;
// { id: string; }
// Parse CSS properties
type CSSProperty =
| 'color'
| 'background-color'
| 'font-size'
| 'margin-top';
type CamelCase<S extends string> = S extends `${infer P1}-${infer P2}${infer P3}`
? `${P1}${Uppercase<P2>}${CamelCase<P3>}`
: S;
type CSSPropertyCamel = CamelCase<CSSProperty>;
// 'color' | 'backgroundColor' | 'fontSize' | 'marginTop'

Key Remapping

Remapping Keys in Mapped Types
typescript
// Filter out specific keys
type OmitByType<T, U> = {
[P in keyof T as T[P] extends U ? never : P]: T[P];
};
interface Mixed {
name: string;
age: number;
isActive: boolean;
count: number;
}
type OnlyStrings = OmitByType<Mixed, number | boolean>;
// { name: string; }
// Rename keys with a prefix
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${string & K}`]: T[K];
};
type PrefixedUser = Prefix<User, 'user_'>;
// { user_id: string; user_name: string; user_email: string; user_age: number; }
// Convert to getter methods
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
Conditional Key Remapping
typescript
// Only include keys that match a condition
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? P : never]: T[P];
};
type NumberProperties = PickByType<Mixed, number>;
// { age: number; count: number; }
// Rename keys based on type
type RenameByType<T> = {
[K in keyof T as T[K] extends string
? `str_${string & K}`
: T[K] extends number
? `num_${string & K}`
: K]: T[K];
};

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
198
Repository forks
21
7-day trend score
26

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 18 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/thebushidocollective/han/typescript-utility-types/badge)](https://verified-skill.com/skills/thebushidocollective/han/typescript-utility-types)

Something wrong with this skill or its page? Tell us.