はじめに
はじめましてこんにちは!@miya_V_i と申します。
文学部出身ですがFEとしてお仕事をしています。
英語はできないのでIT用語やカタカナ用語が苦手です。
こんな記事です
ちょっと難解なTypeScript。今日は少し視点を変えて「言葉」の面から理解して、苦手意識を払拭してみませんか?という記事です。
こんな人向けです
- TypeScriptを勉強したけど、用語が覚えられない。
- TypeScript書けるけど、用語や仕組みの説明には自信がない。
- 文系理系と括られるのは好きじゃないけど、なんとなくTypeScriptのドキュメントって難しいと思う。
実際、用語が覚えられなくてもTypeScriptは書き始められると思います。
とにかくコード書いた方が早いだろって人もいると思います。
そうかもしれない...けど、読み終わった時に、なんか言葉って面白い!なんだかいつもよりTypeScriptを理解できた!という気分になっていただけたら幸いです。
この記事で扱う用語
- リテラル【literal】
- タプル【tuple】
- インターフェース【interface】
- ジェネリクス【generics】
- ユーティリティ【utility】
リテラル【literal】
リテラルとは?
「その値しか受け付けないよ!」という決まりを記述する型をリテラル型と呼びます。
// 朝ごはんはパンしか受け付けない
let breakfast: 'パン' = 'パン';
// パン以外はNG
breakfast = 'ごはんと味噌汁';
breakfast = 'カツ丼';
リテラルの辞書的な意味を読もう
リテラルは、「文字通りの」という意味に加えて、 「正確な」「融通の効かない」 という意味合いも持ちます。とても頑固なTypeScriptらしさがあります。
語源はletter(手紙)などと同じで、「文字の」という意味を持つラテン語だそうです。リテラ...リタァ...レタァ...似ていますね。
リテラル型は、「文字通りのものしか受け付けない正確な」型です。
【参考】リテラル型が活躍する場面は?
リテラル型はユニオン型との組み合わせで使われることも多いです。
ユニオン型は「この中のどれかだったら受け付けてもいいよ!」という、少し寛容な制限になります。
// 晩ごはんはこの中のどれかだったら受け付ける
let dinner = 'ピザ' | 'お好み焼き' | 'カレーとナン';
// どれかにあてはまればOK
dinner = 'ピザ';
// どれにもあてはまらないものはNG
dinner = 'たこ焼き';
タプル【tuple】
タプルとは?
「その順番で、その値しか受け付けないよ!」という配列の形式で決まりを記述する型をタプル型と呼びます。
以下の例は全てstring型を使いましたが、他の型(numberやboolean型など)を組み合わせてもOKというところもポイントです。
// この順番でしか食べない。値そのものの変更や順序の入れ替えは認めない。
let lunch:['サラダ', 'ハンバーグ', 'ライス', '食後のコーヒー'];
// 少しでも値や順序が違うのはNG
lunch = ['ハンバーグ', 'ライス', 'サラダ', '食後のコーヒー'];
lunch = ['サラダ', '照り焼きチキン', 'ライス', '食後のコーヒー'];
タプルの辞書的な意味を読もう
タプルは「複数の要素が一つになった組」という意味を持つ言葉です。
「ダブル」とか「トリプル」は日常生活でもよく聞く言葉で、それらと同じ語源だそうです。
タプル型は、「複数の要素が一つになった」型です。
インターフェース【interface】
インターフェースとは?
複数のオブジェクトに共通して使いたい決まりを宣言するものをインターフェースと呼びます。
// ドリンクメニューオブジェクトに共通する項目と型を宣言する
interface DrinkMenu {
name: stirng;
price: number;
}
// 「継承」と呼ばれる方法で、共通する項目を含むインターフェースを新しく作ることもできる
interface Coffee extends DrinkMenu {
type: 'hot' | 'ice';
sugar: boolean;
milk: boolean;
}
インターフェースの辞書的な意味を読もう
インターフェースと言われた時にエンジニアとして思い浮かべるのは「境界面」「接点」あたりが先かもしれません。UI(ユーザーインターフェース)とか。
しかし、「仲立ち、連絡(係)」というようなニュアンスでも使うようですね。「結び付ける」という捉え方をすると、共通項目の宣言にinterfaceを使うのも納得ですね。
もともとinterfeceという言葉は近年になってIT業界で生まれた造語であり、「相互作用」という意味が強いらしいです。
インターフェースは、(継承されることで)複数のオブジェクトを結び付ける役割を担います。
ジェネリクス【generics】
ジェネリクスとは?
どんな型でも同じ処理を実行する関数を作りたいときに使うのがジェネリクスです。
関数定義のタイミングでは引数の型を「T」という文字で仮置きしておき、
関数を呼び出すタイミングで引数の型を指定して使うことができます。
// メニュー番号でもメニュー名でも共通の処理を施したいときはTを置いておく
cosnt createOrderList = <T>(...order: T[]) => {
return order;
};
// 呼び出すときに引数の型を指定すればOK
createOrderList<number>(2,33,18);
createOrderList<string>('ランチセットB', 'チョコレートパフェ');
応用的な使い方は割愛しますが、ジェネリクスはクラスやインターフェースにも使えます。
ジェネリクスの辞書的な意味を読もう
ジェネリクスは想像がつきやすいかもしれないのですが、よく耳にする「ジェネリック」「ゼネラル」と同じ「一般的な」「共通している」という意味を持ちます。
「特定のブランドに囚われない」と言った意味も含むようで、データ型に囚われない関数に使うもの、と覚えることができます。
ジェネリクスは、データ型に囚われずに関数を定義できる&実行時には引数の型を指定できるので安全!
ユーティリティ【utility】
ユーティリティとは?
既存の型を再利用して新しい型を定義するのに使うものをユーティリティ型と呼びます。
既存の型をどう使うかによってそれぞれユーティリティ型が存在するのですが、以下では一部を抜き出すPick<T,K>
(←ジェネリクスですね!Pick<T,K>
の公式ドキュメントはこちら)を紹介します。
// (例)既存の型から部分的に抜き出して新しい型を作る「Pick<T,K>」を使ってみる。
// デザートメニューに共通する項目と型を決める
type DesertMenuData = {
name: string;
price: number;
}
// 先ほど定義した項目の一部を抜き出して判定に使用したい
const isLunchSetDesert = (data: Pick<DesertMenuData, 'price'>):boolean => {
// 400円以下ならランチセットにプラスできる
return data.price =< 400;
}
ユーティリティの辞書的な意味を読もう
ユーティリティとは「実用的な」「役立つ」「万能」という意味を持ちます。
形容詞だと「どんな役でもこなせる」と言う意味があるのが面白いですね。
この記事で紹介した「Pick」以外にも、さまざまなユーティリティ型があり、必須項目を作ったり、一部を取り除いたりと、まさにユーティリティ型は万能に働く型と言えそうです。
ユーティリティは、ジェネリクスと組み合わせて万能に働く型
最後に
「言葉」の観点からTypeScriptを読み解いてみました。小難しく見える用語たちですが、この記事を読んで少しでも親しみを持ってもらえたり、議論になった際には「あぁ、あの役割のあれね!」と思い出してもらえたりしたら嬉しいです。