はじめに
typescriptって最初なんか使いづらいですよね。。。僕も嫌いでした。
でも寄り添ううちになんとなく僕たちの考え方と似てるのかもしれないと思えるようになってきました。
今回は実案件をもとに具体例をあげて、typescriptの「手なづけ型」をいくつかあげていきたいと思います。
パターン1:普通の型
やること(処理する変数)は明確に指示しましょう。
const numberVal: number = 1; //数字
const stringVal: string = 'string'; //文字列
パターン2:配列の型
[]つければ配列ってわかってくれるみたい。
const numArray: number[] = [1, 2, 3, 4, 5]; //中身が数Number(数字)の配列
const stringArray: string[] = ['1', '2', '3', '4'] //中身がString(文字列)の配列
パターン3:オブジェクトの型
型のチェック表を別で作る感覚?・・・・
明確な答えがあれば安心するのはわかる気がする、、、
interface objectType { // これがobjectの型定義、キーごとに型指定しないといけない
id: number;
title: string;
data: number[];
}
const objectVal: objectType = {
id: 1,
title: `タイトル`,
data: [1, 2, 3, 4, 5]
}
dataはもしかしたらそもそもないかもしれないとなった場合。
interfaceの無いかもしれないキーに「?」をつけます。
interface objectType {
id: number;
title: string;
data?: number[]; // ワンチャン無いかもしれないわこのデータ。。。
}
const objectVal: objectType = {
id: 1,
title: `タイトル`,
data: [1, 2, 3, 4, 5],
}
const objectVal2: objectType = {
id: 2,
title: `タイトル2`,
}
パターン4:オブジェクトの中のオブジェクト
APIとかで取得したデータを整理したいときとかって結構多い気がする。
interface dataType { //objectTypeのdataの型
member: string[];
location: string;
phone: number;
}
interface objectType { //objectの型
id: number;
title: string;
data: dataType;
}
const objectData: objectType = {
id: 184184,
title: '退勤します',
data: {
member: ['山田', '清水', '田中'],
location: 'モナコ公国理想の職場1-17',
phone: 44444444,
}
}
パターン5: elementの型(HTML)
HTMLのエレメントは特別扱いしてあげるみたい。
<div class='element'>
エレメント
</div>
const element = document.querySelector<HTMLElement>('.element'); //DOMを取得するときは<HTMLElement>
複数の場合
<div class='element'>
エレメント
</div>
<div class='element'>
エレメント2
</div>
<div class='element'>
エレメント3
</div>
const element = document.querySelectorAll<HTMLElement>('.element');// 複数の時もあんまり変わらないね
パターン6: 引数の関数
あんまないけど、引数に関数を渡したいときも外で定義しないとダメっぽい
webAPI使うときとかに使うかも?
//関数の型定義(今回はobserverを使うときに自動で入ってくる引数を設定)
type observeFunction = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void;
// 関数の引数に関数を渡すためにobserveFunctionの方を設定
const observeStart = (triggerElements: NodeListOf<HTMLElement>, triggerFunction: observeFunction) => {
const options = {
root: null,
rootMargin: '0px',
threshold: 0.1
};
const scrollObserver = new IntersectionObserver(triggerFunction, options);
for (const trigger of triggerElements) {
scrollObserver.observe(trigger)
}
}
// 引数用の関数1
const scrollFunction = (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
for (const entry of entries) {
const triggerElement = entry.target;
if (entry.isIntersecting) {
console.log('画面に映った!', triggerElement);
} else {
console.log('画面に映ってない!', triggerElement)
}
}
}
// 引数用の関数2
const animtionFunction = (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
for (const entry of entries) {
const triggerElement = entry.target;
if (entry.isIntersecting) {
console.log("アニメーションスタート", triggerElement);
} else {
console.log("アニメーションストップ", triggerElement);
}
}
}
// 発火
document.addEventListener("DOMContentLoaded", () => {
const scrollTrigger = document.querySelectorAll<HTMLElement>(".scroll-trigger");
observeStart(scrollTrigger, scrollFunction);
const animationTrigger = document.querySelectorAll<HTMLElement>(".animation-trigger");
observeStart(animationTrigger, animtionFunction);
});
これは前回のobserverを使ったスクロールアニメーションについて解説した時に使った型定義です。
詳しくは前回の記事を参考に(【javascript】observerで絵本の表紙をリッチにしてみた)
パターン7: ライブラリの型
ニッチな機能以外はほとんどライブラリを使うと思います。(というか使いましょう。)
今ある有名なほとんどのライブラリは、デフォルトでtype(型)定義ファイルが入っているので、脳死でtypescriptで使えるのですが、時々ない場合があります。その場合、
「ライブラリ名 type」で検索
誰かが書いてくれたやつとかあれば、npm installするだけでとりあえず使えます。
見つからない場合は自力で型定義するかライブラリを変えましょう。
最後に
こんな感じでだんだんてなづけるようになれました。
最初はいちいち型定義したり、nullチェックしたりするのがめんどくさかったのですが、今ではないとコーディングできない体に、、、
なんだかんだ複雑な処理や、大きなプロジェクトになるとtypescriptって実は便利なんだなと実感しました。