0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Typescript] as constの活用

Last updated at Posted at 2023-09-29

Literal Union の検証

ユニオンタイプは多分Typescriptで一番よく使われるタイプの一つだと思います。色んなタイプを組み合わせてマージされた形ですが、特定の変数が色んな形のタイプを持つ場合、便利に使うことができます。

特に、Mapped Typeを定義する時、keyのタイプをユニオンで指定することはよくあることです。

ただ、このユニオンタイプには一つの問題があり、それは特定の変数が特定のユニオンに属するかどうかを直接的に検証することができないということです。

しかし、もしユニオンがリテラル型で構成されている場合、as const を使ってこの問題を解決することができます。

type Fruit = 'apple', 'banana', 'grape';

このようなユニオンがあるとする。

まず、このユニオンに属するリテラル型を配列にします。 そして、この配列の後ろに as const を付けて、要素を read-only な状態にします。

const fruitList = ['apple', 'banana', 'grape'] as const;

完成された配列を持ってlookup typeを使ってユニオンを新しく定義することができます。lookup typeが分からない場合はこのリンクを参考してください。

const fruitList = ['apple', 'banana', 'grape'] as const;

type Fruit = typeof fruitList[number];

これで fruitList を利用して type guard を実装できるようになりました。

function isFruit(val: any): val is Fruit {
  if (fruitList.includes(val)) return true;
  return false;
}

Object Literal での活用

下記のような object があるとします。

const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
}

この object の value を引数として受ける関数を作りたい場合はどうすればいいでしょう。

const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
}

function goAbroad(
  from: 'tokyo' | 'seoul' | 'beijing',
  to: 'tokyo' | 'seoul' | 'beijing'): string {
  ...
}

このように一つ一つ書く方法もありますが、この方法があまり満足できないことは誰もが知っているでしょう。

ここでも as const が輝きます。


const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
} as const

type Capital = typeof capitals[keyof typeof capitals]
// Capital === 'japan' | 'korea' | 'china'

function goAbroad(from: Capital, to: Capital): string {
  ...
}

どういうことが起こっているのか説明しますと、まずtypeof capitalsは次のようなタイプを返すことになります。

type typeOfCapitals = typeof capitals;
// type typeOfCapitals = {
//    readonly japan: "tokyo";
//    readonly korea: "seoul";
//    readonly china: "beijing";
// }

ここに keyof をつけると、次のような値が得られます。

type keyOfTypeOfCapitals = keyof typeof capitals;
// type keyOfTypeOfCapitals = 'japan' | 'korea' | 'china'

これで、上で説明した lookup type を利用した方法で再びユニオンを作ることができます。

type keyOfTypeOfCapitals = keyof typeof capitals;
type Capital = typeof Capital[keyOfTypeOfCapitals];
// Capital === 'tokyo' | 'seoul' | 'beijing'
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?