TypeScript、面白いけど新しく覚えることが多い! せや、まとめよう!
というわけで忘備録 兼 理解したことをまとめている記事です。
どなたかのお力になれば幸いです。
interfaceって?
型の情報だけを持ついわゆる構造体。
意図しているtypeを含んだ構造体を使って、その値にどんな型が含まれるべきかを制御できます。
declareを使って書くこともできる。
/*
* item.createdDateを返します。
*/
function convertItem (item) {
return item.createdDate;
}
// このままだと itemにcreatedDateが含まれていない場合でも使用できてしまったり、
// createdDateがどんな形式なのかわからないのであとあと困ることに繋がる。
// これをTypeScriptで置き換えると
// 以下のように型定義を使って、引数に入る値を制御することができ、返却値も明示的にでき、可読性やバグ認知度があがる
// 以下の場合だと、引数に Itemのオブジェクトが期待されているので、他の型の値は使えない。
// 返却値も string型であると明示されているのでこの処理の結果も分かりやすくなっている。
// 引数Itemの型定義
interface Item {
id: number,
createdDate: string,
}
/*
* item.createdDateを返します。
*/
convertItem (item: Item): string {
return item.createdDate;
}
Type Assertion(型アサーション)
TypeScript では型付けを行い、引数や返却値の型を明示的にすることができます。
特に、JavascriptからTypeScriptへ移行していく際に、適宜 型Assertionを行い
どういった値が引数に使えるのか、その処理の結果どういった値が返却されるのかなどを
を明示的にすることが多いです。
(具体的には 頑張ってtypeofなどを使って型判定している部分をTypeScriptで置き換えて分かりやすくする)
// UpdateRequestの型定義
interface UpdateRequest {
id: number,
name: string,
}
const hoge = {} as UpdateRequest;
hoge.id = 1 // => OK
hoge.name = "MyName" // => OK
hoge.id = "1" // => エラー
hoge.name = 123 // => エラー
// こっちの書き方もできる
const AnotherRequest = {
id: 2,
name: "SecondName"
} as UpdateRequest;
// あとからプロパティ追加もできない
AnotherRequest.updateFlag = true; // エラー
type assertion 注意点
type assertionは便利ですが、悪用することも可能です。
as any
を使うことで any型として判定させることができ、コンパイルエラーを回避することができます。
ただし、typescriptの型付けの恩恵を受けられなくなるといったデメリットがあります。
ちなみにそういったコンパイルエラーの場合、だいたいどこかで型が意図せず変換されてしまっているか、どこかで何かを間違えているかなので、まずは自分のコードを疑ったほうがよいかも知れませんね
interface UpdateRequest {
id: number,
name: string,
}
//
const badRequest = {
id: 2,
name: "SecondName"
} as UpdateRequest;
// あとからプロパティ追加できない
badRequest.updateFlag = true; // エラー
const copiedRequest = badRequest as any;
// これなら入ってしまう。 型付けの恩恵を受けられなくなるデメリット
copiedRequest.updateFlag = true; // OK
intersection
あるインターフェースと別のインターフェースを合体させて作る簡易的な interfaceです。
すでに存在しているinterfaceを組み合わせてinterfaceを作れるので、とても便利で取り回しが良いです。
interface FavaoriteFood {
sushi: Sushi;
}
interface FavoriteDrink {
drink: GreenTea;
}
type FavoriteLunch = FavaoriteFood & FavoriteDrink;
// 以下と同じ扱い
// interface FavoriteLunch {
// sushi: Sushi;
// drink: GreenTea;
// }
// 以下のように interface内でも使える
interface Sushi {
sumeshi: Vinegar & Rice,
neta: Fish | Shellfish,
}
所感
まだまだ TypeScriptに触り始めたばかりなので、他の機能もどんどん試していってここに追記していきたいと思います
Type関連だけでもいろんなテクニックやどんどん追加される機能があるので理解したら随時更新します。
参考
- https://typescript-jp.gitbook.io/deep-dive/type-system/type-assertion
-
https://qiita.com/markey/items/134386ee98b277f181f7
- (intersectionの名前を知らなくてググったときに教えていただいた記事です。)
- https://future-architect.github.io/typescript-guide/index.html