スキル一覧に戻る
mgd34msu

typescript

by mgd34msu

Plug in, Receive good vibes.

2🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: typescript description: Adds static typing to JavaScript with TypeScript including type annotations, interfaces, generics, and advanced type utilities. Use when setting up TypeScript projects, defining types, creating generic utilities, or debugging type errors.

TypeScript

Strongly typed programming language that builds on JavaScript, providing type safety and improved developer experience.

Quick Start

Initialize in existing project:

npm install -D typescript
npx tsc --init

Create React project with TypeScript:

npm create vite@latest my-app -- --template react-ts

Key tsconfig.json options:

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "include": ["src"]
}

Basic Types

Primitives

// String
let name: string = 'Alice';

// Number
let age: number = 30;
let price: number = 19.99;

// Boolean
let isActive: boolean = true;

// Null and Undefined
let nothing: null = null;
let notDefined: undefined = undefined;

// Symbol
let id: symbol = Symbol('id');

// BigInt
let bigNumber: bigint = 100n;

Arrays

// Array of strings
let names: string[] = ['Alice', 'Bob'];

// Alternative syntax
let numbers: Array<number> = [1, 2, 3];

// Tuple (fixed length, specific types)
let tuple: [string, number] = ['Alice', 30];

// Readonly array
let readonlyArr: readonly number[] = [1, 2, 3];

Objects

// Inline object type
let user: { name: string; age: number } = {
  name: 'Alice',
  age: 30,
};

// Optional properties
let config: { host: string; port?: number } = {
  host: 'localhost',
};

// Index signature
let dictionary: { [key: string]: number } = {
  one: 1,
  two: 2,
};

Type Aliases and Interfaces

Type Aliases

// Object type
type User = {
  id: string;
  name: string;
  email: string;
};

// Union type
type Status = 'pending' | 'active' | 'completed';

// Intersection type
type Admin = User & {
  role: 'admin';
  permissions: string[];
};

// Function type
type Callback = (error: Error | null, result: string) => void;

Interfaces

interface User {
  id: string;
  name: string;
  email: string;
}

// Extending interfaces
interface Admin extends User {
  role: 'admin';
  permissions: string[];
}

// Declaration merging (interfaces only)
interface User {
  age?: number; // Adds to existing User interface
}

// Implementing interfaces
class UserService implements User {
  id = '1';
  name = 'Alice';
  email = 'alice@example.com';
}

When to Use Which

FeatureTypeInterface
Object shapesBothBoth
Union/IntersectionYesNo (use extends)
PrimitivesYesNo
Declaration mergingNoYes
Class implementsBothBoth

Rule of thumb: Use interface for public APIs (mergeable), type for complex types.

Union and Intersection Types

Union Types

type Result = string | number;
type Status = 'pending' | 'success' | 'error';

function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

Intersection Types

type HasId = { id: string };
type HasTimestamp = { createdAt: Date; updatedAt: Date };

type Entity = HasId & HasTimestamp;

const entity: Entity = {
  id: '1',
  createdAt: new Date(),
  updatedAt: new Date(),
};

Discriminated Unions

type Success = {
  status: 'success';
  data: string;
};

type Error = {
  status: 'error';
  error: string;
};

type Result = Success | Error;

function handleResult(result: Result) {
  switch (result.status) {
    case 'success':
      console.log(result.data); // TypeScript knows data exists
      break;
    case 'error':
      console.log(result.error); // TypeScript knows error exists
      break;
  }
}

Functions

Basic Functions

// Parameter and return types
function greet(name: string): string {
  return `Hello, ${name}!`;
}

// Arrow function
const add = (a: number, b: number): number => a + b;

// Optional parameters
function greet(name: string, greeting?: string): string {
  return `${greeting ?? 'Hello'}, ${name}!`;
}

// Default parameters
function greet(name: string, greeting = 'Hello'): string {
  return `${greeting}, ${name}!`;
}

// Rest parameters
function sum(...numbers: number[]): number {
  return numbers.reduce((a, b) => a + b, 0);
}

Function Overloads

function parse(value: string): number;
function parse(value: number): string;
function parse(value: string | number): string | number {
  if (typeof value === 'string') {
    return parseInt(value, 10);
  }
  return value.toString();
}

const num = parse('123'); // number
const str = parse(123);    // string

Async Functions

async function fetchUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

// With error handling
async function fetchUser(id: string): Promise<User | null> {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) return null;
    return response.json();
  } catch {
    return null;
  }
}

Generics

Generic Functions

// Basic generic
function identity<T>(value: T): T {
  return value;
}

const num = identity(42);      // number
const str = identity('hello'); // string

// Multiple type parameters
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

// Constrained generic
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: 'Alice', age: 30 };
const name = getProperty(user, 'name'); // string

Generic Interfaces

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

interface PaginatedResponse<T> {
  items: T[];
  page: number;
  pageSize: number;
  total: number;
}

const usersResponse: PaginatedResponse<User> = {
  items: [],
  page: 1,
  pageSize: 10,
  total: 0,
};

Generic Classes

class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);

Utility Types

Built-in Utilities

interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

// Partial - all properties optional
type PartialUser = Partial<User>;

// Required - all properties required
type RequiredUser = Required<User>;

// Pick - select specific properties
type UserPreview = Pick<User, 'id' | 'name'>;

// Omit - exclude specific properties
type UserWithoutId = Omit<User, 'id'>;

// Readonly - all properties readonly
type ReadonlyUser = Readonly<User>;

// Record - object with specific key/value types
type UserRoles = Record<string, User>;

// Extract - extract union members
type AdminRole = Extract<User['role'], 'admin'>; // 'admin'

// Exclude - exclude union members
type NonAdminRole = Exclude<User['role'], 'admin'>; // 'user'

// NonNullable - remove null and undefined
type NonNullString = NonNullable<string | null>; // string

// ReturnType - get function return type
type FetchReturn = ReturnType<typeof fetch>; // Promise<Response>

// Parameters - get function parameter types
type FetchParams = Parameters<typeof fetch>; // [input: RequestInfo, init?: RequestInit]

Custom Utility Types

// Make specific properties optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

type UserWithOptionalEmail = PartialBy<User, 'email'>;

// Make specific properties required
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

// Deep partial
type DeepPartial<T> = T extends object
  ? { [P in keyof T]?: DeepPartial<T[P]> }
  : T;

// Deep readonly
type DeepReadonly<T> = T extends object
  ? { readonly [P in keyof T]: DeepReadonly<T[P]> }
  : T;

Type Guards

typeof Guards

function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase(); // value is string
  }
  return value.toFixed(2); // value is number
}

instanceof Guards

function handleError(error: Error | string) {
  if (error instanceof Error) {
    console.log(error.message);
  } else {
    console.log(error);
  }
}

in Guards

interface Dog {
  bark(): void;
}

interface Cat {
  meow(): void;
}

function speak(animal: Dog | Cat) {
  if ('bark' in animal) {
    animal.bark();
  } else {
    animal.meow();
  }
}

Custom Type Guards

interface User {
  type: 'user';
  name: string;
}

interface Admin {
  type: 'admin';
  name: string;
  permissions: string[];
}

function isAdmin(person: User | Admin): person is Admin {
  return person.type === 'admin';
}

function greet(person: User | Admin) {
  if (isAdmin(person)) {
    console.log(`Admin ${person.name} with permissions: ${person.permissions}`);
  } else {
    console.log(`User ${person.name}`);
  }
}

Mapped Types

// Make all properties nullable
type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};

// Add prefix to property names
type Prefixed<T, Prefix extends string> = {
  [P in keyof T as `${Prefix}${string & P}`]: T[P];
};

// Filter properties by type
type StringProperties<T> = {
  [P in keyof T as T[P] extends string ? P : never]: T[P];
};

Conditional Types

// Basic conditional
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

// Infer keyword
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type FnReturn = GetReturnType<() => string>; // string

// Distributive conditional types
type ToArray<T> = T extends any ? T[] : never;

type StrOrNumArray = ToArray<string | number>; // string[] | number[]

// Flatten array type
type Flatten<T> = T extends Array<infer U> ? U : T;

type Str = Flatten<string[]>;  // string
type Num = Flatten<number>;    // number

React Types

import { ReactNode, FC, ComponentProps, PropsWithChildren } from 'react';

// Props with children
interface CardProps {
  title: string;
  children: ReactNode;
}

// Using PropsWithChildren
type ButtonProps = PropsWithChildren<{
  onClick: () => void;
  variant?: 'primary' | 'secondary';
}>;

// Get props from component
type InputProps = ComponentProps<'input'>;
type DivProps = ComponentProps<'div'>;

// Extend HTML element props
interface ButtonProps extends ComponentProps<'button'> {
  variant?: 'primary' | 'secondary';
}

// Event types
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {};

Best Practices

  1. Enable strict mode - Catch more errors at compile time
  2. Prefer interfaces for objects - Better error messages, extensible
  3. Use type for unions - Type aliases handle unions better
  4. Avoid any - Use unknown for truly unknown types
  5. Leverage inference - Don't over-annotate obvious types
  6. Use const assertions - as const for literal types

Common Mistakes

MistakeFix
Using any everywhereUse unknown or proper types
Not enabling strict modeSet "strict": true
Ignoring type errorsFix them or use proper assertions
Over-typingLet TypeScript infer when obvious
Not using genericsAdd type parameters for reusability

Reference Files

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です