概要: このチュートリアルでは、未知の値の型チェックを強制するための TypeScript の unknown 型について学びます。
TypeScript の unknown 型の概要
TypeScript では、unknown 型は、事前に不明な値であり、型チェックが必要な値を保持できます。
unknown 型の変数を宣言するには、次の構文を使用します。
let result: unknown;Code language: TypeScript (typescript)any 型と同様に、unknown 型の変数には任意の値を代入できます。例:
let result: unknown;
result = 1;
result = 'hello';
result = false;
result = Symbol();
result = { name: 'John' };
result = [1, 2, 3];Code language: TypeScript (typescript)any 型とは異なり、TypeScript は、操作を実行する前に型をチェックします。
たとえば、unknown 値に対してメソッドを呼び出したり、演算子を適用したりすることはできません。そうしようとすると、TypeScript コンパイラはエラーを発行します。
let result: unknown;
result = [1,2,3];
const total = result.reduce((a: number, b:number ) => a + b, 0);
console.log(total);Code language: TypeScript (typescript)この例では、result 変数は unknown 型です。配列を result 値に代入しますが、その型は依然として unknown です。したがって、その配列に対して reduce() メソッドを呼び出すことはできません。
result 変数に対して reduce() メソッドを呼び出すには、型アサーションを使用し、TypeScript コンパイラに、result の型が配列であることを明示的に伝える必要があります。例:
let result: unknown;
result = [1, 2, 3];
const total = (result as number[]).reduce((a: number, b: number) => a + b, 0);
console.log(total); // 6Code language: TypeScript (typescript)この例では、result の型が数値の array であることを TypeScript コンパイラに明示的に伝えています(result as number[])。
したがって、問題なく result 配列に対して reduce() メソッドを呼び出すことができます。
Unknown 型 vs Any 型
次の表は、unknown 型と any 型の主な違いをまとめたものです。
| 機能 | any | unknown |
|---|---|---|
| 型安全性 | 型安全ではない | 型安全性を強制 |
| 操作 | チェックなしで操作を実行可能 | 型アサーション(型の絞り込み)なしで操作を実行できない |
| ユースケース | 動的な値に役立つが、安全ではない。 | 動的な値に役立ち、使用前に検証が必要なため安全。 |
| 型チェック | TypeScript コンパイラは、any 変数に対して型チェックを実行しない。 | TypeScript コンパイラは、unknown 変数に対して型チェックを強制する。 |
| 一般的なシナリオ | JavaScript コードベースを TypeScript に移行するために使用。 | 型検証が必要な外部ソース(API呼び出し、データベースなど)からのデータを処理する場合に使用。 |
TypeScript unknown 型の例
TypeScript の unknown 型を使用する実用的な例をいくつか見てみましょう。
1) 外部データの処理
外部APIからデータを受信する際に、unknown 型を使用して、処理する前に検証を強制できます。
次の例は、fetch メソッドを使用して、https://jsonplaceholder.typicode.com/posts エンドポイントから API を呼び出す方法を示しています。
const fetchData = async (url: string): Promise<unknown> => {
const response = await fetch(url);
return await response.json();
};
const showPosts = async () => {
const url = 'https://jsonplaceholder.typicode.com/posts';
try {
const posts = await fetchData(url); // unknown type
(
posts as { userId: number; id: number; title: string; body: string }[]
).map((post) => console.log(post.title));
} catch (err) {
console.log(err);
}
};
showPosts();Code language: TypeScript (typescript)仕組み。
まず、URLからAPIを呼び出し、JSONデータを返す関数fetchDataを定義します。返されるデータの形状が不明なため、関数は Promise<unknown> 値を返します。
const fetchData = async (url: string): Promise<unknown> => {
const response = await fetch(url);
return await response.json();
};Code language: TypeScript (typescript)次に、fetchData() 関数を使用して、エンドポイント https://jsonplaceholder.typicode.com/posts から API を呼び出す showPosts() 関数を定義します。
const showPosts = async () => {
const url = 'https://jsonplaceholder.typicode.com/posts';
try {
const posts = await fetchData(url); // unknown type
(
posts as { userId: number; id: number; title: string; body: string }[]
).map((post) => console.log(post.title));
} catch (err) {
console.log(err);
}
};Code language: TypeScript (typescript)この例では、posts 変数は unknown 型です。
title プロパティにアクセスする前に、型アサーションを使用して、TypeScript コンパイラに post オブジェクトの配列として扱うように指示します。
posts as { userId: number; id: number; title: string; body: string }[]Code language: TypeScript (typescript)3番目に、showPosts() 関数を呼び出します。
showPosts();Code language: TypeScript (typescript)2) 型安全なインターフェイスの作成
次の例では、コンソールにログを出力する前に値をフォーマットする関数 format を定義します。
function format(value: unknown): void {
switch (typeof value) {
case 'string':
console.log('String:', value.toUpperCase());
break;
case 'number':
console.log('Number:', value.toFixed(2));
break;
default:
console.log('Other types:', value);
}
}Code language: TypeScript (typescript)この例では、値のメソッドにアクセスする前に、操作が有効であることを保証するために、その型を検証します。
まとめ
unknown型は、any 型に似ていますが、より制限的です。- 外部ソースから取得したデータで、使用前に検証が必要な場合は、
unknown型を使用してください。