TypeScript の any 型と unknown 型
コードを開発する時点では不明な値を使用することが必要になる場合があります。 このような場合は、any
型と unknown
型および型アサーションと型ガードを使用して、渡された値に対してコードで実行できることを制御できます。
任意の型
any
型は、制約なしに任意の JavaScript 値を表すことができる 1 つの型です。 any
型を使うと異なる型の値を代入し直すことができるため、この型は、サードパーティのライブラリやユーザー入力からの動的な値が予想される場合に便利です。 また、前に説明したように、any
型を使用すると、TypeScript で使用する型が静的になるように、JavaScript コードを段階的に移行することができます。
次の例では、any
型の変数を宣言し、それに値を割り当てています。
let randomValue: any = 10;
randomValue = 'Mateo'; // OK
randomValue = true; // OK
any
型は可能なすべての型の値に対応するので、この例をコンパイルしてもエラーはスローされません。 any
型は型チェックから除外され、これらの値のプロパティの呼び出し、構築、アクセスを行う前にチェックを行う必要はありません。
この例で any
型を使用すると、次のものを呼び出すことができます。
- 型に存在しないプロパティ。
- 関数としての
randomValue
。 string
型にのみ適用されるメソッド。
randomValue
は any
として登録されているため、次の例はすべて有効な TypeScript であり、コンパイルタイム エラーは生成されません。 ただし、ランタイム エラーは、変数の実際のデータ型に応じて発生する可能性があります。 上記の例では、randomValue
がブール値に設定されている場合、実行時に次のコード行で問題が発生します。
console.log(randomValue.name); // Logs "undefined" to the console
randomValue(); // Returns "randomValue is not a function" error
randomValue.toUpperCase(); // Returns "randomValue is not a function" error
重要
any
のすべての便利さには、タイプ セーフが失われるという代償が伴うことにご注意ください。 タイプ セーフは、TypeScript を使用する主な動機の 1 つです。 必要でない限り、any
を使用しないようにしてください。
unknown 型
any
型は柔軟ですが、予期しないエラーが発生するおそれがあります。 この問題に対処するため、unknown
型が TypeScript に導入されました。
unknown
型は、任意の値を unknown
型に割り当てることができる点は、any
型に似ています。 ただし、unknown
型のプロパティにアクセスしたり、その型の呼び出しや構築を行ったりすることはできません。
次の例は、前の例の any
型を unknown
に変更したものです。 このようにすると、型チェック エラーが発生するようになり、適切に対処して解決するまでコードをコンパイルできなくなります。
let randomValue: unknown = 10;
randomValue = true;
randomValue = 'Mateo';
console.log(randomValue.name); // Error: Object is of type unknown
randomValue(); // Error: Object is of type unknown
randomValue.toUpperCase(); // Error: Object is of type unknown
Note
any
と unknown
の主な違いは、unknown
型の変数は操作できないことです。これを行うと、コンパイラ エラーが生成されます。 any
の場合は、コンパイル時のチェックはすべて省略され、オブジェクトは実行時に評価されます。メソッドまたはプロパティが存在する場合、予期したとおりに動作します。
型アサーション
変数を異なるデータ型として扱う必要がある場合は、型アサーションを使用できます。 型アサーションを使用すると、ステートメントを呼び出す前に必要なすべての特別なチェックを実行したことが、TypeScript に通知されます。 "信頼してください、わかってやっています" ということをコンパイラに伝えます。型アサーションは他の言語の型キャストに似ていますが、データの特別なチェックや再構築は実行されません。 実行時の効果はなく、コンパイラによってのみ使用されます。
型アサーションには 2 つの形式があります。 1 つは as
構文です。
(randomValue as string).toUpperCase();
もう 1 つのバージョンは、"山かっこ" の構文です。
(<string>randomValue).toUpperCase();
Note
推奨される構文は as
です。 TypeScript の一部のアプリケーション (JSX など) では、< >
を型変換に使用すると混乱するおそれがあります。
次の例では、型アサーションを使用して toUpperCase
メソッドを呼び出す前に、必要なチェックを実行して、randomValue
が string
であることを確認しています。
let randomValue: unknown = 10;
randomValue = true;
randomValue = 'Mateo';
if (typeof randomValue === "string") {
console.log((randomValue as string).toUpperCase()); //* Returns MATEO to the console.
} else {
console.log("Error - A string was expected here."); //* Returns an error message.
}
TypeScript は、必要なチェックが行われたものと想定するようになります。 型アサーションにより、randomValue
は string
として処理する必要があること、そして toUpperCase
メソッドを適用できることが示されます。
型ガード
前の例では、if
ブロック内で typeof
を使用して、実行時に式の型を確認する方法が示されています。 この条件テストは、型ガードと呼ばれます。
JavaScript で typeof
と instanceof
を使用して、これらの条件をテストする方法は、使用したことがあるかもしれません。 if
ブロックで使用すると、これらの条件が TypeScript によって認識され、型の推定が適切に変更されます。
次の条件を使用して、変数の型を学習できます。
種類 | Predicate |
---|---|
string |
typeof s === "string" |
number |
typeof n === "number" |
boolean |
typeof b === "boolean" |
undefined |
typeof undefined === "undefined" |
function |
typeof f === "function" |
array |
Array.isArray(a) |