実務にて、wideningの抑制のためのas constや、型チェックするためのsatisfiesを利用するルールが浸透してきたので、まとめてみました。
as const
最初にas constのみの場合について説明します。
文字列の場合
const foo = "foo" as const;
としておけば、foo
はリテラル型("foo"型
)であることを保証され、意図しないwideningを防ぐことができます。
numberやbooleanについても同様で、
const num = 777 as const;
const fls = false as const;
としておけば、それぞれ777型、false型のリテラル型となります。
オブジェクトの場合
オブジェクトの場合は、下記のように使用します。
const obj = {
foo: "foo",
bar: 777,
foobar: true
} as const;
オブジェクトの場合、as const を使用しないと、各プロパティはリテラルとは推論されないが(上記fooならstirng型)、as const を使用することで全プロパティがリテラル型になります。
const obj = {
foo: "foo",//"foo"型
bar: 777, //777型
foobar: true //true型
} as const;
obj.foo = "bar"; //怒られる
使い所
定数をexportする際、予期しないところで型wideningが起きてしまうこと可能性があるため、積極的にas const を使う。
satisfies
次に、satisfiesのみの場合について説明します。
例えば、下記のようなオブジェクト(キー名は"red"
, "blue"
, "green"
のどれか、valueは string または number[])があるとします。
type ColorList = {
[key in "red" | "blue" | "green"]: string | number[];
};
const colorList = {
red: "#ff0000",
green: [0, 255, 0],
blue: "#0000ff"
} satisfies ColorList;
console.log(colorList.white);
//------------------- ~~~~~怒られる(そんなプロパティない)
let yelow = colorList.red = "yelow";
// string型と推論され、wideningしており、怒られない
satisfiesを使うことで、型チェックはされているものの、プロパティはwideningしてしまっています。それでは困る場合にas const とsatisfiesを組み合わせます。
as const と satisfiesの組み合わせ
2つを組み合わせるとさらに強力になり、satisfiesによる型チェックと、as const によるwideningの抑制ができるようになります。
type ColorList = {
[key in "red" | "blue" | "green"]: string | number[];
};
const colorList = {
red: "#ff0000",
green: [0, 255, 0],
blue: "#0000ff"
}as const satisfies ColorList;
console.log(colorList.white);
//------------------- ~~~~~怒られる(そんなプロパティない)
let yelow = colorList.red = "yelow";
//------------------- ~~~怒られる(redはreadOnlyだよ)
このように書くことで、型チェックも入り、型推論も保持し、wideningを抑制することができるようになりました。
参考
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html
https://zenn.dev/tonkotsuboy_com/articles/typescript-as-const-satisfies
https://speakerdeck.com/tonkotsuboy_com/typescript-4-dot-9noas-const-satisfiesgabian-li-160d825b-7765-4c2b-945d-bb72cc389557
https://qiita.com/Yametaro/items/494c6e69f7e9bede2197