JavaScript

【TypeScript】Type Assertion(型アサーション)とは

マナビト
マナビト
こんにちはマナビトです。
普段はフロントエンドエンジニアとしてJavaScript/TypeScript/Aangular/GraphQLを
メインに開発業務を行なっています。

以前TypeScriptの基本的な型の宣言について記事にしたと思いますが、
今回はTypeScriptの型アサーションについて解説していきたいと思います。

型アサーションとは

公式ドキュメントによると、TypeScriptにおける型アサーションは下記の通り説明されています。

TypeScriptが推論、分析された型は、任意の方法で上書きできます。これは、型アサーション(type assertion)と呼ばれるメカニズムによって行われます。

TypeScriptには記載されたコーディングの周辺情報や文脈に基づいて、変数の型を推論、分析する型推論の機能が備わっていて、この型推論の機能を使用して、推論された型を上書きすることができます。

例えば、公式ドキュメントの文脈に沿って下記の様に記載すると、エラーが発生します。

let hoge = {};
hoge.age = 25;  // Error: property 'bar' does not exist on `{}`
hoge.name = 'Manabito'; // Error: property 'bas' does not exist on `{}`

hogeには{}を設定しており、オブジェクトの中にプロパティを入れておらず、空のため、ageやnameを設置して追加しようとしても、エラーが返ってくるというわけです。
これは型アサーションを使用して、修正することができます。

interface Foo {
    age: number;
    name: string;
}

let hoge = {} as hoge; //ここに型アサーションを追加する。 
foo.age = 25;
foo.name = 'manabito';


変数を任意の型に変換できるので、私も実務で使うことがあります。

<hoge>とas hogeの違い

as hogeという書き方意外にも、<hoge>という書き方もあります。
as hogeと同様に、任意の型に変換することができます。ですが<hoge>の場合、HTMLタグと同じような記述になり文法表現が曖昧になってしまいますので、あまりお勧めはされていません。(個人的にはそこまで気にならないので、たまに使ってますが...)

let hoge: number;

let bar = <string> hoge; // bar is now of type "string"

型アサーションの弊害

一見便利な型アサーションですが、注意点があります。
型アサーションは任意の型に上書きができるため、TypeScriptの肝である型の安全性が保証されなくなります。型の安全性が保証されないということは、構文の間違いに気付きにくくなり、実行時に初めて気が付くことになります。
下記の場合、オブジェクトの中に必要なプロパティを記載する必要がありますが、プロパティが足りていなくてコンパイルが通ってしまいます。

interface hoge {
  age: number;
  name: string;
};

let bar = {} as hoge; //必要なプロパティを記載しなくても、TypeScriptの型チェックが入らずにエラーが出ない。 


型を初期化したい場合は、極力型アサーションを使用するのではなく、変数に型を明記していく方法が望ましいかと思います。こうすることで、コンパイルエラーが働く様になります。

intserface foo {
  age: number;
  name: string;
}

let bar:foo = {
 age: 24;
}
//Property 'name' is missing in type '{ age: number; }' but required in type 'foo'

型アサーションの使いどころ

結局のところ、型アサーションはひとまず目の前のコンパイルエラーをなんとか解決したいという場合に利用します。型の安全性が保証されないため、むやみに使用するのではなく、極力エラーを解消するための応急処置的な位置付けで捉えてもらえたらと思います。

constアサーションについて

余談になりますが、最後にconstアサーションを紹介しておきたいと思います。
constアサーションを使用することで、指定した全ての値をreadonly(読み取り専用)にすることができます。

const hoge = {
    name: "manabito";
    age: 25;
    city: "Osaka";
} as const;

hoge.name = "masyu";
// Cannot assign to 'name' because it is a read-only property.

上記例では、オブジェクトリテラルにas constを指定しているため、nameに値を代入しようとすると、エラーが発生してしまいます。

const hoge = {
    name: "manabito";
    age: 25;
    city: "Osaka";
};

hoge.name = "masyu";

as constを取り除くと、通常通り代入することができます。

const hoge = {
    name: "manabito";
    age: 25;
    city: "Osaka";
};

hoge.name = "masyu";


本日はここまでとなります。最後までお読みいただきありがとうございました。

参考文献