🎯

typescript-advanced-types

🎯Skill

from flpbalada/my-opencode-config

VibeIndex|
What it does

Enables advanced TypeScript type manipulation through generics, conditional types, mapped types, and utility types for creating robust, type-safe applications.

πŸ“¦

Part of

flpbalada/my-opencode-config(40 items)

typescript-advanced-types

Installation

πŸ“‹ No install commands found in docs. Showing default command. Check GitHub for actual instructions.
Quick InstallInstall with npx
npx skills add flpbalada/my-opencode-config --skill typescript-advanced-types
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.

Overview

# TypeScript Advanced Types

Comprehensive guidance for mastering TypeScript's advanced type system including generics, conditional types, mapped types, template literal types, and utility types for building robust, type-safe applications.

When to Use This Skill

  • Building type-safe libraries or frameworks
  • Creating reusable generic components
  • Implementing complex type inference logic
  • Designing type-safe API clients
  • Building form validation systems
  • Creating strongly-typed configuration objects
  • Implementing type-safe state management
  • Migrating JavaScript codebases to TypeScript

Core Concepts

1. Generics

Purpose: Create reusable, type-flexible components while maintaining type safety.

Basic Generic Function:

```typescript

function identity(value: T): T {

return value;

}

const num = identity(42); // Type: number

const str = identity("hello"); // Type: string

const auto = identity(true); // Type inferred: boolean

```

Generic Constraints:

```typescript

interface HasLength {

length: number;

}

function logLength(item: T): T {

console.log(item.length);

return item;

}

logLength("hello"); // OK: string has length

logLength([1, 2, 3]); // OK: array has length

logLength({ length: 10 }); // OK: object has length

// logLength(42); // Error: number has no length

```

Multiple Type Parameters:

```typescript

function merge(obj1: T, obj2: U): T & U {

return { ...obj1, ...obj2 };

}

const merged = merge(

{ name: "John" },

{ age: 30 }

);

// Type: { name: string } & { age: number }

```

2. Conditional Types

Purpose: Create types that depend on conditions, enabling sophisticated type logic.

Basic Conditional Type:

```typescript

type IsString = T extends string ? true : false;

type A = IsString; // true

type B = IsString; // false

```

Extracting Return Types:

```typescript

type ReturnType = T extends (...args: any[]) => infer R ? R : never;

function getUser() {

return { id: 1, name: "John" };

}

type User = ReturnType;

// Type: { id: number; name: string; }

```

Distributive Conditional Types:

```typescript

type ToArray = T extends any ? T[] : never;

type StrOrNumArray = ToArray;

// Type: string[] | number[]

```

Nested Conditions:

```typescript

type TypeName =

T extends string ? "string" :

T extends number ? "number" :

T extends boolean ? "boolean" :

T extends undefined ? "undefined" :

T extends Function ? "function" :

"object";

type T1 = TypeName; // "string"

type T2 = TypeName<() => void>; // "function"

```

3. Mapped Types

Purpose: Transform existing types by iterating over their properties.

Basic Mapped Type:

```typescript

type Readonly = {

readonly [P in keyof T]: T[P];

};

interface User {

id: number;

name: string;

}

type ReadonlyUser = Readonly;

// Type: { readonly id: number; readonly name: string; }

```

Optional Properties:

```typescript

type Partial = {

[P in keyof T]?: T[P];

};

type PartialUser = Partial;

// Type: { id?: number; name?: string; }

```

Key Remapping:

```typescript

type Getters = {

[K in keyof T as get${Capitalize}]: () => T[K]

};

interface Person {

name: string;

age: number;

}

type PersonGetters = Getters;

// Type: { getName: () => string; getAge: () => number; }

```

Filtering Properties:

```typescript

type PickByType = {

[K in keyof T as T[K] extends U ? K : never]: T[K]

};

interface Mixed {

id: number;

name: string;

age: number;

active: boolean;

}

type OnlyNumbers = PickByType;

// Type: { id: number; age: number; }

```

4. Template Literal Types

Purpose: Create string-based types with pattern matching and transformation.

Basic Template Literal:

```typescript

type EventName = "click" | "focus" | "blur";

type EventHandler = on${Capitalize};

// Type: "onClick" | "onFocus" | "onBlur"

```

String Manipulation:

```typescript

type UppercaseGreeting = Uppercase<"hello">; // "HELLO"

type LowercaseGreeting = Lowercase<"HELLO">; // "hello"

type CapitalizedName = Capitalize<"john">; // "John"

type UncapitalizedName = Uncapitalize<"John">; // "john"

```

Path Building:

```typescript

type Path = T extends object

? { [K in keyof T]: K extends string

? ${K} | ${K}.${Path}

: never

}[keyof T]

: never;

interface Config {

server: {

host: string;

port: number;

};

database: {

url: string;

};

}

type ConfigPath = Path;

// Type: "server" | "database" | "server.host" | "server.port" | "database.url"

```

5. Utility Types

Built-in Utility Types:

```typescript

// Partial - Make all properties optional

type PartialUser = Partial;

// Required - Make all properties required

type RequiredUser = Required;

// Readonly - Make all properties readonly

type ReadonlyUser = Readonly;

// Pick - Select specific properties

type UserName = Pick;

// Omit - Remove specific properties

type UserWithoutPassword = Omit;

// Exclude - Exclude types from union

type T1 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// Extract - Extract types from union

type T2 = Extract<"a" | "b" | "c", "a" | "b">; // "a" | "b"

// NonNullable - Exclude null and undefined

type T3 = NonNullable; // string

// Record - Create object type with keys K and values T

type PageInfo = Record<"home" | "about", { title: string }>;

```

Advanced Patterns

Pattern 1: Type-Safe Event Emitter

```typescript

type EventMap = {

"user:created": { id: string; name: string };

"user:updated": { id: string };

"user:deleted": { id: string };

};

class TypedEventEmitter> {

private listeners: {

[K in keyof T]?: Array<(data: T[K]) => void>;

} = {};

on(event: K, callback: (data: T[K]) => void): void {

if (!this.listeners[event]) {

this.listeners[event] = [];

}

this.listeners[event]!.push(callback);

}

emit(event: K, data: T[K]): void {

const callbacks = this.listeners[event];

if (callbacks) {

callbacks.forEach(callback => callback(data));

}

}

}

const emitter = new TypedEventEmitter();

emitter.on("user:created", (data) => {

console.log(data.id, data.name); // Type-safe!

});

emitter.emit("user:created", { id: "1", name: "John" });

// emitter.emit("user:created", { id: "1" }); // Error: missing 'name'

```

Pattern 2: Type-Safe API Client

```typescript

type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";

type EndpointConfig = {

"/users": {

GET: { response: User[] };

POST: { body: { name: string; email: string }; response: User };

};

"/users/:id": {

GET: { params: { id: string }; response: User };

PUT: { params: { id: string }; body: Partial; response: User };

DELETE: { params: { id: string }; response: void };

};

};

type ExtractParams = T extends { params: infer P } ? P : never;

type ExtractBody = T extends { body: infer B } ? B : never;

type ExtractResponse = T extends { response: infer R } ? R : never;

class APIClient>> {

async request<

Path extends keyof Config,

Method extends keyof Config[Path]

>(

path: Path,

method: Method,

...[options]: ExtractParams extends never

? ExtractBody extends never

? []

: [{ body: ExtractBody }]

: [{

params: ExtractParams;

body?: ExtractBody;

}]

): Promise> {

// Implementation here

return {} as any;

}

}

const api = new APIClient();

// Type-safe API calls

const users = await api.request("/users", "GET");

// Type: User[]

const newUser = await api.request("/users", "POST", {

body: { name: "John", email: "john@example.com" }

});

// Type: User

const user = await api.request("/users/:id", "GET", {

params: { id: "123" }

});

// Type: User

```

Pattern 3: Builder Pattern with Type Safety

```typescript

type BuilderState = {

[K in keyof T]: T[K] | undefined;

};

type RequiredKeys = {

[K in keyof T]-?: {} extends Pick ? never : K;

}[keyof T];

type OptionalKeys = {

[K in keyof T]-?: {} extends Pick ? K : never;

}[keyof T];

type IsComplete =

RequiredKeys extends keyof S

? S[RequiredKeys] extends undefined

? false

: true

: false;

class Builder = {}> {

private state: S = {} as S;

set(

key: K,

value: T[K]

): Builder> {

this.state[key] = value;

return this as any;

}

build(

this: IsComplete extends true ? this : never

): T {

return this.state as T;

}

}

interface User {

id: string;

name: string;

email: string;

age?: number;

}

const builder = new Builder();

const user = builder

.set("id", "1")

.set("name", "John")

.set("email", "john@example.com")

.build(); // OK: all required fields set

// const incomplete = builder

// .set("id", "1")

// .build(); // Error: missing required fields

```

Pattern 4: Deep Readonly/Partial

```typescript

type DeepReadonly = {

readonly [P in keyof T]: T[P] extends object

? T[P] extends Function

? T[P]

: DeepReadonly

: T[P];

};

type DeepPartial = {

[P in keyof T]?: T[P] extends object

? T[P] extends Array

? Array>

: DeepPartial

: T[P];

};

interface Config {

server: {

host: string;

port: number;

ssl: {

enabled: boolean;

cert: string;

};

};

database: {

url: string;

pool: {

min: number;

max: number;

};

};

}

type ReadonlyConfig = DeepReadonly;

// All nested properties are readonly

type PartialConfig = DeepPartial;

// All nested properties are optional

```

Pattern 5: Type-Safe Form Validation

```typescript

type ValidationRule = {

validate: (value: T) => boolean;

message: string;

};

type FieldValidation = {

[K in keyof T]?: ValidationRule[];

};

type ValidationErrors = {

[K in keyof T]?: string[];

};

class FormValidator> {

constructor(private rules: FieldValidation) {}

validate(data: T): ValidationErrors | null {

const errors: ValidationErrors = {};

let hasErrors = false;

for (const key in this.rules) {

const fieldRules = this.rules[key];

const value = data[key];

if (fieldRules) {

const fieldErrors: string[] = [];

for (const rule of fieldRules) {

if (!rule.validate(value)) {

fieldErrors.push(rule.message);

}

}

if (fieldErrors.length > 0) {

errors[key] = fieldErrors;

hasErrors = true;

}

}

}

return hasErrors ? errors : null;

}

}

interface LoginForm {

email: string;

password: string;

}

const validator = new FormValidator({

email: [

{

validate: (v) => v.includes("@"),

message: "Email must contain @"

},

{

validate: (v) => v.length > 0,

message: "Email is required"

}

],

password: [

{

validate: (v) => v.length >= 8,

message: "Password must be at least 8 characters"

}

]

});

const errors = validator.validate({

email: "invalid",

password: "short"

});

// Type: { email?: string[]; password?: string[]; } | null

```

Pattern 6: Discriminated Unions

```typescript

type Success = {

status: "success";

data: T;

};

type Error = {

status: "error";

error: string;

};

type Loading = {

status: "loading";

};

type AsyncState = Success | Error | Loading;

function handleState(state: AsyncState): void {

switch (state.status) {

case "success":

console.log(state.data); // Type: T

break;

case "error":

console.log(state.error); // Type: string

break;

case "loading":

console.log("Loading...");

break;

}

}

// Type-safe state machine

type State =

| { type: "idle" }

| { type: "fetching"; requestId: string }

| { type: "success"; data: any }

| { type: "error"; error: Error };

type Event =

| { type: "FETCH"; requestId: string }

| { type: "SUCCESS"; data: any }

| { type: "ERROR"; error: Error }

| { type: "RESET" };

function reducer(state: State, event: Event): State {

switch (state.type) {

case "idle":

return event.type === "FETCH"

? { type: "fetching", requestId: event.requestId }

: state;

case "fetching":

if (event.type === "SUCCESS") {

return { type: "success", data: event.data };

}

if (event.type === "ERROR") {

return { type: "error", error: event.error };

}

return state;

case "success":

case "error":

return event.type === "RESET" ? { type: "idle" } : state;

}

}

```

Type Inference Techniques

1. Infer Keyword

```typescript

// Extract array element type

type ElementType = T extends (infer U)[] ? U : never;

type NumArray = number[];

type Num = ElementType; // number

// Extract promise type

type PromiseType = T extends Promise ? U : never;

type AsyncNum = PromiseType>; // number

// Extract function parameters

type Parameters = T extends (...args: infer P) => any ? P : never;

function foo(a: string, b: number) {}

type FooParams = Parameters; // [string, number]

```

2. Type Guards

```typescript

function isString(value: unknown): value is string {

return typeof value === "string";

}

function isArrayOf(

value: unknown,

guard: (item: unknown) => item is T

): value is T[] {

return Array.isArray(value) && value.every(guard);

}

const data: unknown = ["a", "b", "c"];

if (isArrayOf(data, isString)) {

data.forEach(s => s.toUpperCase()); // Type: string[]

}

```

3. Assertion Functions

```typescript

function assertIsString(value: unknown): asserts value is string {

if (typeof value !== "string") {

throw new Error("Not a string");

}

}

function processValue(value: unknown) {

assertIsString(value);

// value is now typed as string

console.log(value.toUpperCase());

}

```

Best Practices

  1. Use unknown over any: Enforce type checking
  2. Prefer interface for object shapes: Better error messages
  3. Use type for unions and complex types: More flexible
  4. Leverage type inference: Let TypeScript infer when possible
  5. Create helper types: Build reusable type utilities
  6. Use const assertions: Preserve literal types
  7. Avoid type assertions: Use type guards instead
  8. Document complex types: Add JSDoc comments
  9. Use strict mode: Enable all strict compiler options
  10. Test your types: Use type tests to verify type behavior

Type Testing

```typescript

// Type assertion tests

type AssertEqual =

[T] extends [U]

? [U] extends [T]

? true

: false

: false;

type Test1 = AssertEqual; // true

type Test2 = AssertEqual; // false

type Test3 = AssertEqual; // false

// Expect error helper

type ExpectError = T;

// Example usage

type ShouldError = ExpectError>;

```

Common Pitfalls

  1. Over-using any: Defeats the purpose of TypeScript
  2. Ignoring strict null checks: Can lead to runtime errors
  3. Too complex types: Can slow down compilation
  4. Not using discriminated unions: Misses type narrowing opportunities
  5. Forgetting readonly modifiers: Allows unintended mutations
  6. Circular type references: Can cause compiler errors
  7. Not handling edge cases: Like empty arrays or null values

Performance Considerations

  • Avoid deeply nested conditional types
  • Use simple types when possible
  • Cache complex type computations
  • Limit recursion depth in recursive types
  • Use build tools to skip type checking in production

Resources

  • TypeScript Handbook: https://www.typescriptlang.org/docs/handbook/
  • Type Challenges: https://github.com/type-challenges/type-challenges
  • TypeScript Deep Dive: https://basarat.gitbook.io/typescript/
  • Effective TypeScript: Book by Dan Vanderkam

More from this repository10

🎯
five-whys🎯Skill

Systematically uncovers root causes of problems through iterative questioning, revealing underlying issues beyond surface-level symptoms.

🎯
social-proof-psychology🎯Skill

Optimizes user trust and conversion by strategically displaying social validation through testimonials, user stats, and expert endorsements.

🎯
cognitive-fluency-psychology🎯Skill

Enhances user comprehension and engagement by applying cognitive fluency principles to simplify information processing across content and interfaces.

🎯
hooked-model🎯Skill

Designs habit-forming products by mapping user triggers, actions, rewards, and investments to create engaging, addictive product experiences.

🎯
cognitive-biases🎯Skill

Applies cognitive bias insights to optimize product design, user experiences, and decision-making strategies by leveraging psychological principles.

🎯
typescript-satisfies-operator🎯Skill

Validates TypeScript object types while preserving precise literal types, preventing type widening and catching type-related errors early.

🎯
typescript-best-practices🎯Skill

Enforces TypeScript best practices and coding standards through comprehensive linting and configuration rules for consistent, high-quality code.

🎯
status-quo-bias🎯Skill

Helps design product changes and migrations by understanding users' psychological resistance to change and creating strategies to overcome status quo bias.

🎯
kanban🎯Skill

Visualize and optimize team workflow by creating Kanban boards that track tasks, limit work-in-progress, and improve delivery efficiency.

🎯
theme-epic-story🎯Skill

I apologize, but I cannot generate a description without seeing the actual content or context of the "theme-epic-story" skill from the repository. Could you provide more details about what this spe...