Tips & Tricks

Claude Code के साथ TypeScript

Claude Code का उपयोग करके typescript सीखें। Practical tips और code examples शामिल हैं।

genericsको Claude Code से自在に操る

TypeScriptのgenericsは、再利用性の高い型safeなcodeをलिखनाためのpowerfulな仕組み है।Claude Codeはgenericsのpatternを深く理解しており、appropriateな型parameterの設計 सेcomplexな制約の記述 तक的確にサポートしてくれ है।

basic ジェネリックfunctionのgenerate

まずはClaude Codeにシンプルなジェネリックfunction generateしてもらいましょう。

> 配列 से重複を除去するジェネリックfunctionをबनाओ。
> オブジェクト配列にもsupportし、keyを指定できる तरहして。
function uniqueBy<T, K extends keyof T>(array: T[], key?: K): T[] {
  if (!key) {
    return [...new Set(array)];
  }
  const seen = new Map<T[K], T>();
  for (const item of array) {
    const value = item[key];
    if (!seen.has(value)) {
      seen.set(value, item);
    }
  }
  return [...seen.values()];
}

// Usage example
const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 1, name: "Alice (duplicate)" },
];

const unique = uniqueBy(users, "id");
// => [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]

K extends keyof T という制約 से、存在しないpropertyを指定するとコンパイル時にerrorになり है।

条件型を使った高度なpattern

Claude Codeは条件型(Conditional Types)も的確にgenerateし है।

> APIresponseの型を、成功時とerror時で分岐するジェネリック型を作って。
> ステータスcodeに応じて型が変わる तरहして。
type ApiResult<T, E = Error> =
  | { status: "success"; data: T; error: never }
  | { status: "error"; data: never; error: E };

type ExtractData<R> = R extends { status: "success"; data: infer D } ? D : never;
type ExtractError<R> = R extends { status: "error"; error: infer E } ? E : never;

// responsehandler
function handleResponse<T>(result: ApiResult<T>): T {
  if (result.status === "success") {
    return result.data; // 型が T に絞り込まれる
  }
  throw result.error;
}

// Usage example
interface User {
  id: string;
  name: string;
}

const result: ApiResult<User> = await fetchUser("123");
const user = handleResponse(result); // 型は User

ジェネリックclassでrepositorypattern

dataアクセス層をgenericsで抽象化するpatternも、Claude Codeに任せると効率的 है।

interface Entity {
  id: string;
  createdAt: Date;
  updatedAt: Date;
}

interface Repository<T extends Entity> {
  findById(id: string): Promise<T | null>;
  findMany(filter: Partial<T>): Promise<T[]>;
  create(data: Omit<T, "id" | "createdAt" | "updatedAt">): Promise<T>;
  update(id: string, data: Partial<Omit<T, "id">>): Promise<T>;
  delete(id: string): Promise<void>;
}

class PrismaRepository<T extends Entity> implements Repository<T> {
  constructor(private model: any) {}

  async findById(id: string): Promise<T | null> {
    return this.model.findUnique({ where: { id } });
  }

  async findMany(filter: Partial<T>): Promise<T[]> {
    return this.model.findMany({ where: filter });
  }

  async create(data: Omit<T, "id" | "createdAt" | "updatedAt">): Promise<T> {
    return this.model.create({ data });
  }

  async update(id: string, data: Partial<Omit<T, "id">>): Promise<T> {
    return this.model.update({ where: { id }, data });
  }

  async delete(id: string): Promise<void> {
    await this.model.delete({ where: { id } });
  }
}

genericsの制約をutilizationしたビルダーpattern

型parameterの制約を組み合わせた型safeなビルダーもgenerateでき है।

type QueryBuilder<T extends Record<string, unknown>> = {
  where<K extends keyof T>(key: K, value: T[K]): QueryBuilder<T>;
  orderBy<K extends keyof T>(key: K, direction: "asc" | "desc"): QueryBuilder<T>;
  select<K extends keyof T>(...keys: K[]): QueryBuilder<Pick<T, K>>;
  execute(): Promise<T[]>;
};

function createQuery<T extends Record<string, unknown>>(
  table: string
): QueryBuilder<T> {
  const conditions: string[] = [];
  const orders: string[] = [];
  let selectedFields: string[] = [];

  const builder: QueryBuilder<T> = {
    where(key, value) {
      conditions.push(`${String(key)} = '${value}'`);
      return builder as any;
    },
    orderBy(key, direction) {
      orders.push(`${String(key)} ${direction}`);
      return builder;
    },
    select(...keys) {
      selectedFields = keys.map(String);
      return builder as any;
    },
    async execute() {
      // 実際のquery実行ロジック
      return [];
    },
  };

  return builder;
}

Claude Codeへの効果的なプロンプト

genericsをClaude Code को requestする際のコツをまとめ है।

  1. 具体的な使用例を示す - 「इस तरहな入出力になるfunction」と伝える
  2. 制約を明示する - 「TはRecord型に限定」 आदि型制約を指定する
  3. ユースケースを複数提示する - 多様なuse करने का तरीकाを示すと精度がऊपरがる
> ジェネリック型 DeepPartial<T> を作って。
> ネストしたオブジェクトのसभीのpropertyをオプショナルにする。
> 配列の要素もDeepPartialにして。
type DeepPartial<T> = T extends (infer U)[]
  ? DeepPartial<U>[]
  : T extends object
    ? { [K in keyof T]?: DeepPartial<T[K]> }
    : T;

Summary

Claude Codeはgenericsのgenerateとoptimizationに非常にpowerful है।型parameterの設計、制約の付与、条件型のutilization आदि、complexなpatternもプロンプト一つでimplementationでき है।

TypeScriptの型utilizationをइसके अलावा深めたい方はTypeScriptdevelopmentを加速する実践Tipsを、utility型の応用はutility型utilizationガイドをदेखें。इसके अलावा, TypeScript公式ハンドブックのgenericsも併せてconfirmすると理解が深まり है।

#Claude Code #TypeScript #generics #type safety #design patterns