TypeScript Academy · レッスン

単位の取り違えを防ぐブランド型・opaque型

基本型にphantom brandプロパティを交差させて単位やタグの取り違えを防ぎ、ファクトリ関数だけで値を生成します

レッスン 1/38 ステップ

「単位の取り違えを防ぐブランド型・opaque型」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン1/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全3レッスンが含まれています。

概要

目標: 型レベルで見た目が同じ値を区別します。通常の number だけではメートルと秒を区別できませんが、ブランドマーカーを使えば区別できます。

  • 実行時のオーバーヘッドがゼロ
  • より安全な API とリファクタリング
  • ファクトリ経由でのみ作成する

プリミティブな単位にブランドを付ける

Brand マーカーによって、コンパイル時に単位を分離できます。引数の順序を間違えると型チェックに失敗します。

type Meter = number & { readonly __brand: "meter" }
type Second = number & { readonly __brand: "second" }

function meter(n: number): Meter { return n as Meter }
function second(n: number): Second { return n as Second }

const d = meter(100)
const t = second(9)

function speed(dist: Meter, time: Second) { return (dist as number) / (time as number) }

// speed(t, d)  // compile error: brands do not match

汎用的な Brand ヘルパー

ドメインをまたいで汎用的な Brand ヘルパーを使用します。型付き ID、トークン、カーソルなどに利用できます。

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

type UserId = Brand<"UserId", string>
type OrderId = Brand<"OrderId", string>

function userId(x: string): UserId { return x as UserId }
function orderId(x: string): OrderId { return x as OrderId }

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

const u = userId("u_123")
const o = orderId("o_456")
// findUser(o) // error: OrderId not assignable to UserId

unique symbol によるブランド付け

unique symbol によるブランド付けにより、名前の衝突やグローバル名前空間への漏れを防げます。

declare const MeterSym: unique symbol

type Meter2 = number & { readonly [MeterSym]: "meter" }

function asMeter2(n: number): Meter2 { return n as Meter2 }

const m2 = asMeter2(5)
// const wrong: Meter2 = 5  // discourage raw assignment; prefer factories

ファクトリとバリデーション

ファクトリの中でブランドを付与します。まず検証し、次にブランドを付け、その後で利用します。呼び出し側で場当たり的に as を使うのは避けてください。

type NonEmptyString = string & { readonly __brand: "NonEmpty" }

function nonEmpty(s: string): NonEmptyString | null {
  return s.trim().length > 0 ? (s as NonEmptyString) : null
}

function makeSlug(s: NonEmptyString) {
  return (s as string).toLowerCase().replace(/\s+/g, "-")
}

const ok = nonEmpty(" Hello ")
if (ok) { makeSlug(ok) }  // safe: validated & branded first

ヒントと注意点

ベストプラクティス:

  • ブランド名は短く、意味が分かるものにしてください。
  • ブランド付きの値を取得する方法は、ファクトリだけにしてください。
  • 必要な場合を除き、公開 API の型にブランドを漏らさないでください。
  • ブランドは型レベルだけのものであり、実行時のオーバーヘッドはありません。

ブランド付けの確認

クイックチェック: 単位やタグの取り違えを防ぐパターンはどれですか。

まとめ

まとめ: ブランド付き型や不透明型によって、見た目が似た値(メートルと秒、UserId と OrderId)を区別できます。ファクトリで生成し、API 全体で利用することで、誤った取り違えをなくせます。

無料で開始

AI チューターと学ぶ TypeScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
101
レッスン
352

よくある質問

「単位の取り違えを防ぐブランド型・opaque型」レッスンは無料ですか?

はい。「単位の取り違えを防ぐブランド型・opaque型」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全3レッスンが含まれています。

「単位の取り違えを防ぐブランド型・opaque型」で何を学びますか?

基本型にphantom brandプロパティを交差させて単位やタグの取り違えを防ぎ、ファクトリ関数だけで値を生成します ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/3です。

「単位の取り違えを防ぐブランド型・opaque型」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 単位の取り違えを防ぐブランド型・opaque型
  2. タグ付きIDとドメインモデリングのパターン
  3. ドメインモデリング — 集約、不変条件、サービス
← TypeScript Academyに戻る