😆

【TypeScript 4.9 beta】satisfies に大満足

2022/09/28に公開
1

少し前に、TypeScript 4.9 betaがリリースされましたね。その中でもsatisfiesオペレータに、「おお!いいやん!」と個人的に興奮したので軽く記事にしたいと思います。

https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/

概要

一言で言うと「typoとかが嫌なので型でしばりたい推論は具体的なままでいてほしい」という想いを実現してくれるのがsatisfiesです。
上記のBlogも十分わかりやすいかと思いますが、本記事では、より簡素な例を用いて説明したいと思います。

以降colorsというオブジェクトを定義すると仮定して、説明を進めます...。

// こんなオブジェクトを定義したい...。

const colors = {
  primary: "#FFFFFF",
  secondary: "#000000",
  tertiary: "#999999"
}

いままでは...

新しい色を追加したいと思った時、型を指定していないとtypoなど、想定外の値を入れてしまう可能性があります。型を指定していなければ自力で気付くしかありません。

 const colors = {
   primary: "#FFFFFF",
   secondary: "#000000",
   tertiary: "#999999",
+  newColor: 343434  // number なってしまっている。
 }

それを避けるためにオブジェクトに型をつけてみます。
keyは文字列で、valueも #FFFFFFのような文字列が入るので、以下のような型をつけます。

+ const colors: Record<string,string> = {
   primary: "#FFFFFF",
   secondary: "#000000",
   tertiary: "#999999",
-  newColor: 343434
+  newColor: "#343434"  // typeErrorが発覚するのでstringに修正
 }

すると型を指定したのでもちろんなのですが、不正な値に対するtypeErrorを教えてくれるようになりました。
typoとかが嫌なので型でしばりたい が実現しました。

しかし逆にcolorsを使用する際の推論は効かなくなってしまいます。

typoとかが嫌なので型でしばりたい をとると 推論は具体的なままでいてほしいが実現できず、
推論は具体的なままでいてほしい をとると typoとかが嫌なので型でしばりたいが実現できません。
今まではそれらの両立を諦めていた方も、これからは違います。ぼくらにはsatisfiesがついています。

これからは...

satisfiesがあるこれからの世界では、今まで両立が難しかった「typoとかが嫌なので型でしばりたい推論は具体的なままでいてほしい」が簡単に実現できてしまいます。

  const colors = {
    primary: "#FFFFFF",
    secondary: "#000000",
    tertiary: "#999999",
+ } satisfies Record<string,string> 

typeErrorも教えてくれつつ、

推論も効かせることができます。

うれしいですね!!
どんなことができそうか色々想像が膨らみますが、個人的には以下のような使い方ができるなぁと思っています。

const colors = {
  primary: "#FFFFFF",
  secondary: "#000000",
  tertiary: "#999999",
  // valueには「#付きの文字列」しか認めない(as const の位置はsatisfiesの前じゃなきゃだめ。)
} as const satisfies Record<string, `#${string}`>

type Color = keyof typeof colors

あとがき

本記事で紹介した例はとても簡素で単純な例ですので、「なんかよさそう」と思った方はMicrosoftのBlogを確認していただくのがいいかと思います!
今までたまに感じていたストレスを消し去ってくれそうなsatisfiesの登場に大満足しています!

playgroundも貼っておきますので遊んでみてくださいね!

https://www.typescriptlang.org/play?ts=4.9.0-dev.20220921#code/C4TwDgpgBASg4gISgXigJwgQwCYHsB2ANiFANobYBcU+ArgLYBGEaANFAOYYT7V1Mt2jQrQh8GzNAF0A3AChQkKAGFchXGhSxEUAD5QAzsDQBLfB3lyAxgSNQwmQhGDBoqAN5yo39BCpkAJgBWIPYABnCpVi8fLggeagAiAGIwsIAzdLTE6J8oYVFqUgBGVgDWAGYouQBfQ0xgEwN0kwgDWAgbNGwAHiNTc3ZVdTQAPksbfAM1CAA6dQ4ACgcnFzm4ngBKeQB6HbyDw7yAPQB+OQvJuyvgTHxgAAVHZ1ctTzyKIuDQqAjf6ryG14UBSaUy2VyPgKYjIpXKVWidUw7Ru9UazVa7RgnQ0vX6Zg4QzUGnGl1sM3muCWNzuj2ea1mQO2cj2RzZ7O8ZzkQA

参考記事

https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/#hamilton

https://dev.to/ayc0/typescript-49-satisfies-operator-1e4i

追記

2022.11.16

2022.11.15に正式版がリリースされました!

https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/

Discussion

kana-chankana-chan

Tappleにも使えそう...?

type MyTapple = [string,...string[]]

const tappleA = ["a","b"] satisfies MyTapple
const tappleB: MyTapple = ["a","b"]

tappleA[0]
tappleA[1]
tappleA[2] // typeError

tappleB[0]
tappleB[1]
tappleB[2] // typeErorrでない。