Claude Code Plugins

Community-maintained marketplace

Feedback

typescript-patterns

@StackOneHQ/stackone-ai-node
9
0

TypeScript patterns and best practices for StackOne SDK

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name typescript-patterns
description TypeScript patterns and best practices for StackOne SDK

TypeScript Patterns and Best Practices

This skill provides guidance on TypeScript patterns and best practices for writing clean, type-safe code in the StackOne SDK.

Exhaustiveness Checking with satisfies never

When branching on string unions, use the satisfies never pattern to guarantee compile-time exhaustiveness without introducing temporary variables.

Pattern:

switch (bodyType) {
  case 'json':
    // ...
    break;
  case 'form':
    // ...
    break;
  case 'multipart-form':
    // ...
    break;
  default: {
    bodyType satisfies never; // Error if new variant added
    throw new Error(`Unsupported HTTP body type: ${String(bodyType)}`);
  }
}

Benefits:

  • Adding a new union member will trigger a compile-time error
  • Keeps union definition and switch statement in sync automatically
  • No temporary variables needed
  • Clear intent about exhaustiveness checking

Avoiding any Type

Always use specific types instead of any when possible.

Bad:

function processData(data: any): any {
  return data.value;
}

Good:

function processData<T extends { value: U }, U>(data: T): U {
  return data.value;
}

// Or with type narrowing
function processData(data: unknown): unknown {
  if (typeof data === 'object' && data !== null && 'value' in data) {
    return (data as Record<string, unknown>).value;
  }
  throw new Error('Invalid data format');
}

Alternatives to any:

  • Use unknown when type is truly not known, then narrow with type guards
  • Use Record<string, unknown> for objects with unknown property values
  • Use union types to represent multiple possible types
  • Use generics with type constraints

Non-null Assertions (!) - Avoid

Never use non-null assertions. Instead, use proper null checking.

Bad:

function getConfig(configMap: Map<string, Config>): Config {
  const config = configMap.get('default');
  return config!; // Dangerous!
}

Good:

function getConfig(configMap: Map<string, Config>): Config {
  const config = configMap.get('default');
  if (!config) {
    throw new Error('Default config not found');
  }
  return config;
}

// Or with optional chaining and nullish coalescing
function getConfig(configMap: Map<string, Config>): Config {
  return configMap.get('default') ?? getDefaultConfig();
}

Parameter Reassignment - Avoid

Create new variables instead of reassigning function parameters.

Bad:

function mergeOptions(options: Options, overrides?: Options): Options {
  options = { ...options, ...overrides }; // Reassignment
  return options;
}

Good:

function mergeOptions(options: Options, overrides?: Options): Options {
  const mergedOptions = { ...options, ...overrides };
  return mergedOptions;
}

Classes with Only Static Members - Avoid

Use namespaces or simple exported functions instead.

Bad:

export class Utils {
  public static formatDate(date: Date): string {
    return date.toISOString();
  }

  public static parseDate(dateStr: string): Date {
    return new Date(dateStr);
  }
}

Good - Namespace:

export namespace Utils {
  export const formatDate = (date: Date): string => {
    return date.toISOString();
  };

  export const parseDate = (dateStr: string): Date => {
    return new Date(dateStr);
  };
}

Better - Simple exports:

export const formatDate = (date: Date): string => {
  return date.toISOString();
};

export const parseDate = (dateStr: string): Date => {
  return new Date(dateStr);
};

Explicit Return Types

Always specify return types for functions.

Bad:

const calculateTotal = (items: Item[]) => {
  return items.reduce((sum, item) => sum + item.price, 0);
};

Good:

const calculateTotal = (items: Item[]): number => {
  return items.reduce((sum, item) => sum + item.price, 0);
};

// Or for function declarations
function calculateTotal(items: Item[]): number {
  return items.reduce((sum, item) => sum + item.price, 0);
}

Property Deletion - Type-Safe Methods

Use proper type-safe methods to remove properties instead of setting to undefined or using delete.

Bad:

function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
  obj['propertyToRemove'] = undefined; // Type error!
  delete obj['propertyToRemove']; // Linter warning
}

Good - Destructuring (Immutable):

function removeProperty(obj: Record<string, JSONSchema7Definition>): Record<string, JSONSchema7Definition> {
  const { propertyToRemove, ...rest } = obj;
  return rest;
}

Good - Delete (In-place):

function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
  delete obj['propertyToRemove'];
}

Recommendations

  1. Use satisfies never for all union type switches
  2. Prefer unknown over any and use type guards
  3. Use optional chaining (?.) and nullish coalescing (??)
  4. Always specify return types
  5. Use destructuring for immutable property removal
  6. Write functions as simple exports, not class static methods
  7. Create new variables instead of reassigning parameters