zukucode
主にWEB関連の情報を技術メモとして発信しています。

TypeScript unknown型を安全に確認して使用する

unknownは、どのような値が入っているか分からないことを表す型です。

外部から受け取ったJSONやcatchした値を、確認せず操作したくない場合に使います。anyは型チェックを無効にしますが、unknownは確認するまで操作を許しません。値が不明であるという事実を型に残すことが、unknownを選ぶ理由です。

anyとの違い

anyは型の確認をせずに操作できます。

const value: any = 10;
value.toUpperCase(); // コンパイルできるが、実行時にエラー

unknownでは、型を確認するまで操作できません。

const value: unknown = 10;
// value.toUpperCase(); // TypeScriptのエラー

外部から受け取る値など、型が分からない値にはunknownを使うと安全です。

typeofで型を確認する

const toUpperCase = (value: unknown): string => {
  if (typeof value !== 'string') {
    return '';
  }

  return value.toUpperCase();
};

typeof value === 'string'を確認した範囲では、TypeScriptがvalueをstring型として扱います。

Errorかどうか確認する

catchで受け取る値も、常にErrorとは限りません。

try {
  await saveData();
} catch (error: unknown) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error('不明なエラーが発生しました。');
  }
}

instanceof Errorを確認してからmessageを参照します。

オブジェクトのプロパティを確認する

type User = {
  userId: string;
  name: string;
};

const isUser = (value: unknown): value is User => {
  if (typeof value !== 'object' || value === null) return false;

  const user = value as Record<string, unknown>;
  return typeof user.userId === 'string'
    && typeof user.name === 'string';
};

戻り値のvalue is Userを型述語と呼びます。

const data: unknown = JSON.parse(jsonText);

if (isUser(data)) {
  console.log(data.name);
}

const user = data as Userと書いても、実際のデータがUser型になるわけではありません。外部データはプロパティを確認するか、検証ライブラリを使用します。

unknownを使うと、型が分からない値を操作する前に確認が必要になり、実行時エラーを減らせます。


関連記事