🐷

[TypeScript] Wideningについて調べてみた

2023/10/18に公開

はじめに

以前TypeScriptのWideningに惑わされたので、今回はWideningの基本的な部分を記事にまとめようと思いました。

constとletの型推論の違い

const foo = 'foo' // fooは"foo"型
let bar = 'bar' // barはstring型

上記のようにconstletでは型推論に違いが出ます。
理由としては、constは再代入不可なのに対して、letは再代入が可能だからです。
仮にletで宣言した変数の型がリテラル型に推論されてしまうと再代入できる意味がなくなってしまいます。
だからこそletの場合はリテラル型ではなくプリミティブ型に推論されます。
ちなみにこれもWideningの一つでstring型に限らずboolean型やnumber型でも同様の挙動になります。

Widening

const foo = 'foo' // fooは"foo"型
let bar = foo // barはstring型

constで宣言した変数(リテラル型)をletで宣言した変数の中に代入すると、勝手に対応するプリミティブ型に拡張されてしまいます。
これがWideningと呼ばれるものになります。

Wideningしてほしくない時

以下の方法を利用してリテラル型を明示的に入れておくことで、Wideningな性質を排除することができ、
letで宣言した変数の型のリテラル型のままになります。

型アノテーション

const foo: 'foo' = 'foo' // fooは"foo"型
let bar = foo // barは"foo"型

型アサーション

const foo = 'foo' as 'foo' // fooは"foo"型
let bar = foo // barは"foo"型

constアサーション

const foo = 'foo' as const // fooは"foo"型
let bar = foo // barは"foo"型

おわり

今回はWideningの基本的をまとめてみました。
オブジェクトのプロパティも再代入が可能なため、オブジェクトリテラルの中でも今回見たようなリテラル型のWideningが発生します。
機会があればそちらについてもまとめてみたいと思います!

参考

https://zenn.dev/estra/articles/typescript-widening#widening
https://gihyo.jp/book/2022/978-4-297-12747-3

Discussion