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 型にのみ適用されるメソッド。

randomValueany として登録されているため、次の例はすべて有効な 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

anyunknown の主な違いは、unknown 型の変数は操作できないことです。これを行うと、コンパイラ エラーが生成されます。 any の場合は、コンパイル時のチェックはすべて省略され、オブジェクトは実行時に評価されます。メソッドまたはプロパティが存在する場合、予期したとおりに動作します。

型アサーション

変数を異なるデータ型として扱う必要がある場合は、型アサーションを使用できます。 型アサーションを使用すると、ステートメントを呼び出す前に必要なすべての特別なチェックを実行したことが、TypeScript に通知されます。 "信頼してください、わかってやっています" ということをコンパイラに伝えます。型アサーションは他の言語の型キャストに似ていますが、データの特別なチェックや再構築は実行されません。 実行時の効果はなく、コンパイラによってのみ使用されます。

型アサーションには 2 つの形式があります。 1 つは as 構文です。

(randomValue as string).toUpperCase();

もう 1 つのバージョンは、"山かっこ" の構文です。

(<string>randomValue).toUpperCase();

Note

推奨される構文は as です。 TypeScript の一部のアプリケーション (JSX など) では、< > を型変換に使用すると混乱するおそれがあります。

次の例では、型アサーションを使用して toUpperCase メソッドを呼び出す前に、必要なチェックを実行して、randomValuestring であることを確認しています。

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 は、必要なチェックが行われたものと想定するようになります。 型アサーションにより、randomValuestring として処理する必要があること、そして toUpperCase メソッドを適用できることが示されます。

型ガード

前の例では、if ブロック内で typeof を使用して、実行時に式の型を確認する方法が示されています。 この条件テストは、型ガードと呼ばれます。

JavaScript で typeofinstanceof を使用して、これらの条件をテストする方法は、使用したことがあるかもしれません。 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)