0Pricing
TypeScript Academy · レッスン

アサーションと型ガード

可能な場合は、アサーションより実行時チェックを優先します。

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

コンパイラーを納得させる2つの方法

コンパイラーが値の正確な型を把握できないときは、2つの選択肢があります。型をアサーションする(その型だと主張する)か、型をガードする(実行時に型を証明する)かです。見た目は似ていますが、安全性は大きく異なります。

function viaAssert(v: unknown): number {
  return (v as number) + 1; // claim
}
function viaGuard(v: unknown): number {
  return typeof v === 'number' ? v + 1 : 0; // prove
}
console.log(viaAssert(5), viaGuard(5), viaGuard('x'));

アサーションは検証しない

アサーションは、強制力のない約束です。間違っていても、バグは実行時まで見つからずに通り抜けます。アサーションは、安全性と引き換えに便利さを得る仕組みです。

const v: unknown = 'hello';
const n = v as number;
console.log(n.toFixed(2)); // runtime error: toFixed is not a function

型ガードは実行時に検証する

型ガードは実際に値をチェックします。チェックに通れば、あなたとコンパイラーの両方が型の正しさを把握できます。型の絞り込みを裏付ける実際の実行時テストがあるからです。

function toFixed2(v: unknown): string {
  if (typeof v === 'number') return v.toFixed(2);
  return 'N/A';
}
console.log(toFixed2(3.14159), toFixed2('hi'));

カスタム型ガード関数

複雑なチェックを、value is T を返す再利用可能なガードにまとめましょう。十分にテストされた1つの検証をコードベース全体で利用できます。

type Email = { address: string };
function isEmail(v: unknown): v is Email {
  return typeof v === 'object' && v !== null &&
    'address' in v && typeof (v as any).address === 'string';
}
console.log(isEmail({ address: 'a@b.com' }), isEmail(null));

ガードは組み合わせて再利用できる

ガードは通常の関数なので、組み合わせたり、テストしたり、再利用したりできます。一方、アサーションはあちこちに散らばる主張であり、中央で検証することはできません。

function isString(v: unknown): v is string { return typeof v === 'string'; }
function isNonEmpty(v: unknown): v is string {
  return isString(v) && v.length > 0;
}
console.log(isNonEmpty('hi'), isNonEmpty(''));

assertsを使ったアサーション関数

TypeScriptにはアサーション関数も用意されています。戻り値のアノテーションでは asserts キーワードを使います。関数が正常に戻ると、コンパイラーはその時点以降、引数の型を絞り込みます。条件が満たされない場合は、関数が例外をスローします。

function assertNumber(v: unknown): asserts v is number {
  if (typeof v !== 'number') throw new Error('not a number');
}
function use(v: unknown): number {
  assertNumber(v); // after this line, v is number
  return v * 2;
}
console.log(use(21));

assertsとvalue isの違い

value is T ガードは、分岐に使うブール値を返します。asserts value is T 関数は失敗時に例外をスローし、そのスコープの残りの部分で型を絞り込みます。どちらも、単なる as とは異なり、実行時のチェックに裏付けられています。

function assertDefined<T>(v: T): asserts v is NonNullable<T> {
  if (v === null || v === undefined) throw new Error('missing');
}
const maybe: string | null = 'ok';
assertDefined(maybe);
console.log(maybe.length); // narrowed to string

汎用アサーションヘルパー

アサーション関数は、再利用可能な前提条件に適しています。1つの assert(condition) ヘルパーでコード全体の不変条件を守り、違反があれば早い段階で例外をスローできます。

function assert(cond: unknown, msg: string): asserts cond {
  if (!cond) throw new Error(msg);
}
function half(n: number): number {
  assert(n % 2 === 0, 'must be even');
  return n / 2;
}
console.log(half(8));

安全性を比較する

安全性の高い順に並べると、型ガードとアサーション関数(実行時にチェックされるもの)が最も安全で、次に通常の as アサーション(チェックされないもの)、最後に二重アサーション(積極的に誤解を招くもの)が続きます。目的に合う、最も安全な手段を選んでください。

// Safe: guard
function safe(v: unknown) {
  return typeof v === 'string' ? v.trim() : '';
}
console.log(safe('  hi  '));

適切な手段を選ぶ

型に基づいて分岐する場合は型ガードを使ってください。前提条件が満たされなければ処理を停止する必要がある場合はアサーション関数を使います。as は、型の絞り込みでは対応できない場合(DOMの特殊化など)に限って使用してください。

function getInput(v: unknown): asserts v is string {
  if (typeof v !== 'string') throw new Error('expected string');
}
const raw: unknown = 'name';
getInput(raw);
console.log(raw.toUpperCase());

実行時チェックが有効

このコースで繰り返し扱ってきたテーマは、アサーションより実行時チェックを優先することです。ガードとアサーション関数なら、コンパイル時の型と実行時の安全性の両方が得られます。アサーションから得られるのは主張だけです。

function parsePort(v: unknown): number {
  if (typeof v === 'number' && Number.isInteger(v)) return v;
  throw new Error('invalid port');
}
console.log(parsePort(8080));

理解度チェック

アサーションと型ガードについての理解度を確認しましょう。

復習:アサーションと型ガード

次のことを学びました。

  • 型ガード(value is T)は実行時に型を証明し、その型に基づいて分岐できるようにします。
  • アサーション関数(asserts value is T)は失敗時に例外をスローし、その後で型を絞り込みます。
  • 通常の as アサーションは型を主張するだけで、実行時の安全性はありません。
  • 実行時にチェックされる手段を優先し、アサーションは型の絞り込みで対応できない場合に限って使用してください。

次のコースでは、オプショナルチェーンとNull合体演算子を扱います。

function isPositive(v: unknown): v is number {
  return typeof v === 'number' && v > 0;
}
console.log(isPositive(5), isPositive(-1));

よくある質問

「アサーションと型ガード」レッスンは無料ですか?

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

「アサーションと型ガード」で何を学びますか?

可能な場合は、アサーションより実行時チェックを優先します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「アサーションと型ガード」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. 型アサーションに使うasキーワード
  2. Non-nullアサーション演算子
  3. 二重アサーションとそのリスク
  4. アサーションと型ガード
← TypeScript Academyに戻る