この記事はWanoグループアドベントカレンダー2020の17日目の記事となります。
こんにちは。アルファアーキテクト株式会社でエンジニアをやっています、stk0724です。(今月Wanoから転籍しました)
ここ一年ほどReact + TypeScriptで広告配信設定管理画面のリニューアルプロジェクトに携わっていたため、TypeScriptの好きなところを書いてみようと思います。(ちなみにバックエンドおじさんなので、フロントエンド専業の人から見るとおかしなことが書いてあるかもしれない。。。
交差型 (Intersection Type)
日本語でいうと、「XかつY」みたいなのを実現する仕組みですね。
コードで書くと以下のようなの。
type Hoge = {
hoge: string
}
type Fuga = {
fuga: string
}
type HogeFuga = Hoge & Fuga
上記の場合、HogeFugaはメンバーとして、hoge, fugaを持つ型となります。
どういうときに使うと嬉しいのか?
メンバーが少しづつ異なる型を多数定義するときに使いました。
以下のような感じです。
type BaseState = {
isLoading: boolean
errorMessage: string
}
type VideoState = BaseState & {
videoData?: VideoData
}
type ThumbnailState = BaseState & {
thumbnailData?: ThumbnailData
}
似たりよったりのフォームがたくさんあるときに、共通項目をベースとなる型で定義しておいて、それを拡張するイメージです。
リテラル型 (とユニオン型)
リテラル型は、JavaScriptのプリミティブな値を型として指定できるというものです。
例えば以下のようなやつ
const name: "stk0724" = "stk0724" //"stk0724"以外代入できない
上記の場合、コメントのとおり型に指定した文字列以外を代入できないため、使い所がありません。
しかし、ユニオン型と組み合わせると素敵なやつに様変わりします。
type WanoGroup = "Wano" | "EDO CODE" | "アルファアーキテクト" | "TuneCore Japan"
const company1: WanoGroup = "Wano"
const company2: WanoGroup = "EDO CODE"
function sayWanoGroup(company: WanoGroup) {
console.log(company)
}
sayWanoGroup(company1)
sayWanoGroup(company2)
sayWanoGroup("アルファアーキテクト") //IDEなどで補完がきく
sayWanoGroup("サルファアーキテクト") //コンパイルエラー
ユニオン型は「XもしくはY」を表現する型です。
リテラル型とユニオン型を組み合わせると、特定の文字列のみを受け付ける型、特定の数値のみを受け付ける型などを表現することができます。
上記の例ですと、Wanoグループの社名のみを受け付けるWanoGroup型を定義しています。
そして、sayWanoGroup関数は引数にWanoGroupをとるので、条件を満たさない文字列を引数に指定するとコンパイルエラーになります。
どういうときに使うと嬉しいのか?
関数の引数にプリミティブ値をとりたいけど、特定の値のみに絞りたい場合などですかね。
あとは単純にENUMの代わりに使うとか。
Mapped Types
複雑な機能なので、説明は公式ドキュメントなどを参照してくだされ。。。
早い話が、既存の型を拡張して動的に型を定義する機能です。
type WanoGroupEmployeeCounts = {[P in WanoGroup]: number;}
const data: WanoGroupEmployeeCounts = {
"wano": 1,
"EDO CODE": 2,
"アルファアーキテクト": 3,
"TuneCore Japan": 4
}
上記の場合、WanoGroupEmployeeCountsは、WanoGroupのメンバをキー、値の型がnumberとなるオブジェクトを表現する型となります。
どういうときに使うとうれしいのか
openapi-generator-cliで出力したモデルを拡張するときに使いました。
openapi-generator-cliで出力したモデルはinterfaceになっており、交差型でそのまま拡張することができなかったためです。
interface Hoge {
frequency: number
price: number
}
type HogeExtended = {[P in keyof Hoge]: Hoge[P];} & {
frequencyString: string
priceString: string
}
上記の場合、まずHogeのメンバーをkeyofで列挙してキーとし、値の型はHogeの対応するキーの値の型をそのままもってきています。
早い話が、interfaceをtypeに変換しています。そして、交差型を使ってメンバーを拡張しています。
終わり
だいたいTypeScriptの型システムの話ですね。
TypeScriptはいいんですが、バックエンドおじさんがAPI書きながら片手間でReact書くのは結構大変でした。(そしてまだリリースできていません。。。)
アルファアーキテクトではエンジニアを絶賛募集中です