tech-book-labs
ガイド(言語 / 開発ツール) · 2 セクション統合

TypeScript 上級活用ガイド

TypeScript の踏み込んだ型テクニック(conditional types / template literal types / branded types など)と、v6 → v7 のメジャーアップグレード時に当たる主要な変更点・移行ノートを 1 ページに統合。実コード付き。

著者:TechBook.net編集部 · 最終検証 2026-05-10
セクション · 2026-05-10 · typescript 6.0.x

TypeScript で template literal / mapped / conditional / branded を組む

TypeScript の高度な型操作 — Template Literal Types で文字列合成、Mapped Type の as でキー変換、Conditional Type の分配的挙動、再帰で Path 抽出、Brand で同型異種を区別するパターンを触れる demo で確認する実装メモ。

検証日: 2026-05-10

使用バージョン: typescript@6.0.x

対象: 入門〜中級は通っている、型レベル計算で API / form / 状態管理を絞り込みたい人

入門 + 移行記事は別途。本稿は 「型は実行時には消えるが、書き手の事故を runtime ではなく compile 時に止める」 ための高度パターン。

触って試す

// 型レベルで文字列を組み立てる
type Method = "GET" | "POST";
type Path = "/users" | "/posts";
type Endpoint = `${Method} ${Path}`;

// 推論結果:
// "GET /users" | "GET /posts" | "POST /users" | "POST /posts"
推論結果
"GET /users" | "GET /posts" | "POST /users" | "POST /posts"
要点

union を ${} に入れると分配的に組み合わせる。HTTP endpoint や CSS class の安全な合成に使える。

5 パターン × コード + 推論結果 + 要点を切替表示。

1. Template Literal Types

型レベルで文字列を組み立てる:

type Method = "GET" | "POST" | "PUT" | "DELETE";
type Path = "/users" | "/posts" | "/comments";
type Endpoint = `${Method} ${Path}`;
// "GET /users" | "GET /posts" | "POST /users" | ...(全 12 通り)

union を ${} に入れると 分配的に組み合わせ が生成される。

Template Literal Types の分配 — union メンバーごとに全組合せが生成される(直積) (クリックで拡大)

実用例:

// CSS class 名を型で縛る
type Size = "sm" | "md" | "lg";
type Color = "primary" | "secondary";
type ButtonClass = `btn-${Size}-${Color}`;

// HTTP endpoint
type ApiPath = `/api/${"users" | "posts"}/${string}`;

// イベント名
type EventName = `on${Capitalize<"click" | "hover" | "focus">}`;
// "onClick" | "onHover" | "onFocus"

Capitalize<T> / Uppercase<T> / Lowercase<T> / Uncapitalize<T>組み込み型変換ユーティリティ が用意されている。

2. Mapped Type + Key Remapping(as 句)

as を使うと 既存型のキー名を template literal で書き換え られる。

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

type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

type UserGetters = Getters<User>;
// {
//   getId: () => string;
//   getName: () => string;
//   getEmail: () => string;
// }

ポイント:

  • string & KK を string 型に narrow(Capitalize は string が必要)
  • as never にすればそのキーを除外(filter としても使える)
  • getter / setter / event 名 prefix / API client method 自動生成 に強い

3. Conditional Type + 分配的(Distributive)

extends を使うと union を分配しながら判定 できる。

type NonEmpty<T> = T extends "" ? never : T;
type ExtractStrings<T> = T extends string ? T : never;

type A = NonEmpty<"a" | "" | "b">;       // "a" | "b"
type B = ExtractStrings<string | number | boolean>;  // string

T が裸の型パラメータの時 自動的に union を分配する。 分配を 無効化したい時 は tuple で囲む:

type IsString<T> = [T] extends [string] ? true : false;
type C = IsString<string | number>;  // false(union 全体が string か?を判定)

type IsStringDistr<T> = T extends string ? true : false;
type D = IsStringDistr<string | number>;  // true | false(member ごとに判定して union)

4. 再帰型で Path 抽出

オブジェクトの ネストしたパス を文字列リテラル union として取り出す典型パターン:

type Path<T, K extends keyof T = keyof T> = K extends string
  ? T[K] extends object
    ? `${K}` | `${K}.${Path<T[K]>}`
    : `${K}`
  : never;

type User = {
  id: string;
  profile: { name: string; address: { city: string; zip: string } };
};

type UserPath = Path<User>;
// "id" | "profile" | "profile.name" | "profile.address"
//   | "profile.address.city" | "profile.address.zip"

実用例:

  • lodash.get(obj, path) の path 引数を型 safe に
  • react-hook-form の register("profile.address.city")(内部で類似の Path 型を持つ)
  • i18n の翻訳キーt("user.profile.name") 形式で型補完

5. Branded Types(同型異種を区別)

UserIdPostId も中身は string。型レベルで取り違えを禁止 したい時に brand を使う。

type Brand<T, B extends string> = T & { readonly __brand: B };

type UserId = Brand<string, "UserId">;
type PostId = Brand<string, "PostId">;

// runtime には何も追加しない、cast で brand を付与
const u = "550e8400-e29b-..." as UserId;
const p = "660b9500-..." as PostId;

function fetchUser(id: UserId) { /* ... */ }

fetchUser(u);     // OK
fetchUser(p);     // ✗ 型エラー(別の brand)
fetchUser("550"); // ✗ 型エラー(plain string)

runtime には型情報が消える ので overhead ゼロ。Zod の .brand<>() も同じ発想を schema レベルで提供。

実用箇所:

  • DB の主キー(UserId / PostId / OrderId が混ざる場面)
  • Money(yen / dollar が同じ number で混在)
  • Sanitized vs Raw の string(XSS 対策)

6. infer で型を抽出

extends の中で infer を使うと、条件にマッチした部分の型を変数に入れて取り出せる

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Awaited<T> = T extends Promise<infer U> ? U : T;
type ArrayItem<T> = T extends Array<infer U> ? U : never;

Promise<X> を分解して X を取り出す、Array<X> から要素型を取り出す、関数の戻り値型を取り出す、など。組み込みの Awaited / ReturnType / Parameters も同じ仕組み。

応用:

// 関数の最初の引数だけ取り出す
type FirstArg<T> = T extends (a: infer A, ...rest: any[]) => any ? A : never;

// tagged template の interpolation 部分を取り出す
type Args<T> = T extends `${string}${infer U}${string}` ? U : never;

7. satisfies(型安全 + リテラル保持)

v4.9+ で導入された satisfies は、型を強制すると同時にリテラル型を保持する。

// NG: const config = {...} as Record<string, string>
//     → リテラル型 "https://..." が string に広がる

// OK: satisfies で型チェックしつつ narrow を維持
const config = {
  api: "https://api.example.com",
  cdn: "https://cdn.example.com",
} satisfies Record<string, string>;

config.api;  // 型は "https://api.example.com" のリテラル

設定オブジェクト / route 定義 / theme tokens すべて satisfies が現代的標準。

8. const 型パラメータ(v5.0+)

generic に const K extends ... を付けると、呼び出し側で as const 不要でリテラル型が保たれる:

function defineRoute<const T extends string>(path: T): { path: T } {
  return { path };
}

const r = defineRoute("/users/:id");
// r.path の型は "/users/:id" リテラル(as const 不要)

ライブラリ作者向け。useRouter / Zod / tRPC のような型推論を厚くしたい API で活躍。

つまずいたポイント

  • 型エラーが分かりにくい時:type _ = T のような中間 alias を作って各段階の推論結果を確認(IDE のホバーで見える)
  • Path<T> を巨大 union に適用するとコンパイル爆発:type SafePath<T> = T extends Record<string, unknown> ? Path<T> : never のように防御
  • Capitalize<K>Kstring | number | symbol の時にエラー:Capitalize<string & K>Capitalize<Extract<K, string>> で string に narrow
  • as cast は危険:branded type の付与以外で多用すると runtime で爆発する
  • 再帰型の depth エラー:Type instantiation is excessively deep、tail-recursive に書き換えるか、深さ制限を引き下げる

関連 Topic / 関連書籍

この記事と関係する tech-book.net の Topic と、それぞれの Topic に紐づく書籍:

tech-book.net /books/9784814401093

Effective TypeScript(第2版) : 型システムの力を最大限に引き出す83項目

Dan Vanderkam/今村 謙士 · オライリージャパン · 2025年 · ¥4,620

急速に普及が進んでいるTypeScriptの実用書! TypeScriptの実用書。TypeScript…

詳細を tech-book.net で見る
tech-book.net /books/9784297129163

TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発

手島 拓也/吉田 健人/高林 佳稀 · 技術評論社 · 2022年

新しいフロントエンドの入門書決定版! 本書はReact/Next.jsとTypeScriptを用いてWebアプリケーションを開…

詳細を tech-book.net で見る
tech-book.net /books/9784297137397

かんたん TypeScript

HIRO · 技術評論社 · 2023年

本書は、「広く・正しく・新しく」をコンセプトにTypeScriptでプログラミングをはじめるにあたって基本的なことはすべて学習できる内容となっています。また、イラストによる図解方式で概念をやさしく解説している…

詳細を tech-book.net で見る
tech-book.net /books/9784297126353

ゼロからわかる TypeScript入門

WINGSプロジェクト 齊藤新三/山田 祥寛
詳細を tech-book.net で見る
tech-book.net /books/9784297127473

プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで

鈴木 僚太 · 技術評論社 · 2022年

TypeScriptは、JavaScriptに静的型付けの機能を加えたオープンソースのプログラミング言語です。本書では、根幹となるJavaScr…

詳細を tech-book.net で見る
セクション · 2026-05-10 · typescript 6.0.x

TypeScript v6/v7 で書く時の注意点

TypeScript v6 系で安定した機能(satisfies / const generics / using / NoInfer)と、v7 で進む方向性、移行で詰まりやすい設定差分を実装観点で整理。

検証日: 2026-05-09

使用バージョン: typescript@6.0.x(現行 stable)

対象: TypeScript v5 系から v6/v7 へ移行する人、新規プロジェクトを v6 ベースで始める人

TypeScript は v5 → v6 のメジャーで内部のリファクタが大きく入り、書き味が一段変わりました。 ここでは v6 で実用的になった書き味 と、v5 から移行する時に詰まる差分 を整理します。

v5 → v6 の主な変更点(俯瞰)

v5 で導入された機能が v6 で標準化される流れ (クリックで拡大)

1. satisfies — 「型の絞り込み」と「型の保証」を両立

v4.9 で入った satisfies 演算子は、v6 系では 設定オブジェクトのデファクト に。

// 従来: 型を強制すると、リテラル型が広がってしまう
const config: Record<string, string> = {
  api: "https://api.example.com",
  cdn: "https://cdn.example.com",
};
config.api;  // string(リテラル型が失われる)

// v6 推奨: satisfies で型をチェックしつつ、リテラル型を保つ
const config = {
  api: "https://api.example.com",
  cdn: "https://cdn.example.com",
} satisfies Record<string, string>;
config.api;  // "https://api.example.com" (リテラル型が保持)

API 設定 / Topic 一覧 / 環境変数の型などで多用するパターン。

satisfies / 型注釈 / as の使い分け

3 つは似て非なるもの。値を「チェックしたいか」「型を広げたい/絞りたいか」で選び分け。

satisfies / 型注釈 / as の選び方 — リテラル型を保ちたい時は satisfies が最強、as は最終手段 (クリックで拡大)
観点型注釈 : Tsatisfies Tas T
構造チェック✗(コンパイラ無視)
リテラル型保持✗(broaden)
型安全性低(誤魔化し)
推奨用途API 引数の値設定オブジェクト全般型システム外との接続

2. const generics — as const を関数引数で

v5 で安定した const 型パラメータ は v6 で広く使われるようになりました。

function pickKeys<const K extends string>(keys: K[]): K[] {
  return keys;
}

const ks = pickKeys(["a", "b", "c"]);  // (\"a\" | \"b\" | \"c\")[]
//                                        ↑ as const 不要

Zod / tRPC / next-safe-action のような型推論重視ライブラリの内部で多用されています。

3. using / 明示的リソース管理(Stage 3 → v6 標準)

using 宣言で、スコープを抜ける時に自動で Symbol.dispose を呼ぶ リソース管理が可能。

function openFile(path: string) {
  const fd = fs.openSync(path, "r");
  return {
    fd,
    [Symbol.dispose]() { fs.closeSync(fd); },
  };
}

{
  using f = openFile("/tmp/data");
  // f を使う処理
}  // ← ここで自動的に close される

Node のファイルディスクリプタ、DB コネクション、トランザクションのスコープ管理に強い。

4. NoInfer<T> — 型推論の方向を制御

v5.4 で追加された NoInfer<T> は、generic の 「推論に使わない引数」 を明示できる。

function createState<T>(initial: T, validator: (v: NoInfer<T>) => boolean) {
  // T は initial からのみ推論される。validator の引数からは推論されない
}

createState({ count: 0 }, (v) => v.count >= 0);
//                          ↑ NoInfer なので {count: number} に正しく型付け

ライブラリ著者向けの機能だが、フォーム validation の resolver や状態管理ライブラリで有用。

5. tsconfig の差分(v5 → v6)

lib: "esnext" の意味が変わる

v6 では ESNext の参照が更新され、新しい組み込み API(Array.fromAsync / Promise.withResolvers / 等)が含まれます。 Node 22+ でないと runtime で動かない API が型として使える ようになるので、targetlib の整合性が重要に。

moduleResolution: "bundler" がほぼ標準

v5 で bundler モードが追加され、v6 ではこれを推奨。Vite / esbuild / Bun 系のプロジェクトはほぼ全て bundler で OK。 旧 node / node16 モードは Node native CommonJS / ESM の解釈が混乱しがちなので避ける。

{
  "compilerOptions": {
    "target": "ES2024",
    "lib": ["ES2024", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "skipLibCheck": true
  }
}

verbatimModuleSyntax が重要

verbatimModuleSyntax: true にすると、import type / export type を省略すると build エラーになります。 v6 系ではこれが標準的な厳しさになっており、Vite / Bun / esbuild と組み合わせる時に必須に近い。

// NG(verbatimModuleSyntax: true 下)
import { User } from "./user";  // User が type-only ならエラー

// OK
import type { User } from "./user";
import { createUser } from "./user";

6. v5 → v6 移行で詰まる箇所

tsc 互換性

  • isolatedDeclarations が v5.5 で追加 → v6 でも引き続き厳しい。.d.ts 自動生成系(API ライブラリ)では効くが、アプリ側ではオプション
  • module: "Preserve" が v6 で追加 → trans-builder(Vite / esbuild)に渡す時の挙動が変わる場合がある
  • tsc --watch のメモリ使用量が v5 系より増える傾向。大規模 monorepo では incremental: truetsBuildInfoFile を必ず指定

依存ライブラリの型互換

  • React 19 の types は v6 系で完全対応。v5.x の途中バージョンは React 19 hooks の型に追いついていない
  • Zod v4 の generic 推論は v6 で IDE 速度がかなり改善
  • 古い @types/ パッケージ* が v6 のバージョン上限を超えている場合がある(tscArgument of type ... is not assignable が出る)

tsconfig 警告

  • v5.x で動いていた一部の // @ts-expect-error が v6 で無視されるケース(エラーが出なくなった箇所)
  • noUncheckedIndexedAccess: true を新規に有効にすると、配列 / オブジェクトアクセスが軒並み undefined 含みになる(これが v6 系で特に影響)

7. v7 系の方向性(2026-05 時点での観察)

  • 型推論の更なる速度改善(generic の deep inference を再構成)
  • Node ESM ↔ CJS 境界の単純化(module: "Preserve" の標準化方向)
  • decorators の更なる安定(Stage 3 → 4 想定)
  • 互換性破壊は最小限という方針が続く

具体的な v7 リリース時期は流動的。ライブラリ作者は v7 リリース後 3〜6 ヶ月の追従、アプリ作者は v6 系で当面安定運用 が現実解。

評価

観点v6 系での評価コメント
型推論速度v5 系より速い、特に Zod / tRPC で顕著
書き味satisfies / const / using で意図が表現しやすい
エコシステム整合React 19 / Astro 6 / Vite 7 と整合済
移行コストtsconfig の verbatimModuleSyntax で全 import 書換えが必要な場合あり

移行時のチェックリスト

  • target / libES2024 以上にして runtime 対応を確認
  • moduleResolution: "bundler" に切替(Vite / esbuild 系)
  • verbatimModuleSyntax: true を有効化、import type 漏れを修正
  • noUncheckedIndexedAccess: true を導入する場合は段階的(エラーが大量に出るので 1 ファイルずつ)
  • @types/* パッケージを最新化(古いバージョンが警告の原因になる)
  • incremental: true + tsBuildInfoFile で watch のメモリ削減
  • React 19 + 各種ライブラリの最新 types に上げる

関連 Topic / 関連書籍

この記事と関係する tech-book.net の Topic と、それぞれの Topic に紐づく書籍:

tech-book.net /books/9784814401093

Effective TypeScript(第2版) : 型システムの力を最大限に引き出す83項目

Dan Vanderkam/今村 謙士 · オライリージャパン · 2025年 · ¥4,620

急速に普及が進んでいるTypeScriptの実用書! TypeScriptの実用書。TypeScript…

詳細を tech-book.net で見る
tech-book.net /books/9784297129163

TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発

手島 拓也/吉田 健人/高林 佳稀 · 技術評論社 · 2022年

新しいフロントエンドの入門書決定版! 本書はReact/Next.jsとTypeScriptを用いてWebアプリケーションを開…

詳細を tech-book.net で見る
tech-book.net /books/9784297137397

かんたん TypeScript

HIRO · 技術評論社 · 2023年

本書は、「広く・正しく・新しく」をコンセプトにTypeScriptでプログラミングをはじめるにあたって基本的なことはすべて学習できる内容となっています。また、イラストによる図解方式で概念をやさしく解説している…

詳細を tech-book.net で見る
tech-book.net /books/9784297126353

ゼロからわかる TypeScript入門

WINGSプロジェクト 齊藤新三/山田 祥寛
詳細を tech-book.net で見る
tech-book.net /books/9784297127473

プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで

鈴木 僚太 · 技術評論社 · 2022年

TypeScriptは、JavaScriptに静的型付けの機能を加えたオープンソースのプログラミング言語です。本書では、根幹となるJavaScr…

詳細を tech-book.net で見る

全ガイドは ガイド一覧 から。連載は 連載一覧 へ。