TypeScript 4.9で追加されたsatisfies
オペレーターですが、「これ何に便利なの?」「使いみちある?」という声を聞くところですが、使いどころのひとつとして、あるかなと思ったのがあったので紹介したいと思います。
僕もsatisfies
オペレーター自体、使い所を模索しているところなので、いちアイディアとして読んでいただければと思います。そのうえで、感想やツッコミなど頂けると嬉しいです。
JavaScriptで書いてた頃
一旦、TypeScriptは忘れて、JavaScriptを書いてた頃のマインドセットでコードを考えてみます。
たとえば、次のようなオブジェクトリテラルをJSONにしたいと考えたとします。
{ id: 1, name: "foo" }
JavaScript脳ならこう書くと思います。
const json = JSON.stringify({ id: 1, name: "foo" });
オブジェクトリテラルをJSON.stringify
関数の引数に直接渡しています。
TypeScriptではどう書きたいか
上のようなコードをTypeScriptで書くならどうするかを考えてみます。
上のJavaScriptコードのままでもいいのですが、JSON.stringify
関数の引数の型はany
型です。そのため、オブジェクトリテラルには型チェックが働いていません。TypeScriptで書いていると、型をどこかで注釈してあげたくなります。そのために、一旦はオブジェクトリテラルを変数にする必要があります。
// 一旦変数にする
const foo: Foo = { id: 1, name: "foo" };
// ^^^型注釈
const json = JSON.stringify(foo);
ここで言いたいのは、JavaScriptでは、オブジェクトリテラルを引数に直接書くのが自然だったのに、TypeScriptになると一時的な変数を書くのが好ましくなる、というケースあるということです。TypeScriptでゼロから書いていると、気にもしないところかもしれませんが、JavaScriptをTypeScriptに移植する場合は、気になってくるところかもしれません。
satisfies
オペレーターの使いみち
TypeScript 4.9からは新たな道具として、satisfies
オペレーターが追加されました。これをごくごく単純に説明すると、「型推論を活かしながら型を注釈できる機能」です。
話を戻して、上の話を振り返ると、JavaScript脳で書いたコードはこれでした。
const json = JSON.stringify({ id: 1, name: "foo" });
これをTypeScriptに書き換えると、こうなりました。
const foo: Foo = { id: 1, name: "foo" };
const json = JSON.stringify(foo);
少ない書き換えではありますが、一時的な変数ができたりと、型チェックのために処理がちょっと変わっています。
処理を一切変えずに、型チェックしたいところですが、今まではできませんでした。
TypeScript 4.9からは、satisfies
オペレーターを使うと、セマンティクスを変えずに型チェックを効かせられるようになります。次のコードがsatisfies
オペレーターを使った例です。
const json = JSON.stringify({ id: 1, name: "foo" } satisfies Foo);
// ^^^^^^^^^^^^^
このようにJavaScript風の書き方を崩さずにTypeScriptで書けるところが、satisfies
オペレーターの使いみちの1つとしてあるのではないかと思いました。「JavaScriptとTypeScriptは別言語だから、それぞれ都合に合わせた書き方をしたほうがいい」という考え方もあると思いますが、個人的には「TypeScriptはJavaScriptに型注釈を追加するための言語で、できる限りJavaScript wayで書きたい、型のために実行時の処理を歪めるのは可能なら避けたい」という思いがあるので、それを実現するひとつのアイディアとして本稿を投稿してみました。