大学生が0から始めたTS勉強
こんにちは。どこにでもいる大学三年生をやらせてもらってます。
Typescriptをjavascriptを軽く触ったくらいの自分が勉強してインプット・アウトプットする過程でまとめたものです。誰かの役に立ったら幸いです。
変数定義
未定義の変数に代入はダメ
型の複数定義
let birthYear: number | string | “北極”;
値も定義可能
変数の巻き上げ(js特有)
varで定義されたものの左辺は関数の先頭で定義。
var A=Bという記述がはじめて出てくるところでAにBが代入される。
varは関数のスコープ外からも読み取れる
const,letはブロックスコープ内
プリミティブ型(最小単位)
リテラル:専用の文法、データ
TSのデータ型種類
・boolean 型
→ture/false
・number 型
→演算子
条件(三項)演算子
condition ? exprIfTrue : exprIfFalse
if文などで使われる。conditionがtrueのとき左の値を返す、falseだと右の値を返す。
Mathオブジェクト
・string 型
→基本シングルorダブルクオーテーション、ただしバッククオートだと改行が反映される
・配列
・オブジェクト
・関数
・undefined
・null
→nullは気楽に使ってはいけない、もし使うなら「AもしくはBのデータが格納できる」という合併型(Union Type)の型宣言ができるので、これをつかって null を代入します
//stringかnullを入れられるという宣言をしてnullを入れる
let favaoriteGame: string | null = null;
文字コードの正規化
"ABCアイウエオ㍻".normalize("NFKC")
'ABCアイウエオ平成'
複合型
複合型:大きなデータを定義できるデータ型
配列
同じような目的の変数を使う時に全ての要素を代表する変数名をつける。ここの要素を「インデックス」という。
// 変数に代入。型名を付けるときは配列に入れる要素の型名の後ろに[]を付与する
const years: number[] = [2019, 2020, 2021];
// 後ろの型が明確であれば型名は省略可能
const divs = ['tig', 'sig', 'saig', 'scig'];
// 配列に要素を追加。複数個も追加可能
years.push(2022);
years.push(2023, 2024);
years[10] = 2029;
// 要素から取り出し
const first = years[0];
タプル
配列の要素ごと型が違う
ただしタプル型は各位置の情報が不明瞭であるため、インターフェースを用いてプロパティを定義すしたほうがよい。
インタフェース:概念的に共通した部分、機能、操作の集まり
ex)
ノード(Node)
└ 要素(Element)
└ HTML要素(HTMLElement)
└ p要素(HTMLParagraphElement)
例えばp要素やli要素にも共通して「コンテントを持つ(textcontentプロパティ)」という機能が備わっているがそれはHTMLParagraphElementの上位概念としてHTMLElementインターフェースとして登録しているから。
インターフェースは「概念」、オブジェクトは「実態」
const movie:[number,string] = [2019,"ゴジラ"]
//インターフェース定義する時
interface momvie{
showingYear:number;
title:string;
}
function getResult():movie{
return{
showingYear:2019
title:"ゴジラ"
};
}
配列からデータを取り出す
TSはJSと異なり、分割代入を用いて複数の値を取り出すことができる。
slice()を使わずに新しい残余(Rest)構文を使って複数取り出すことも可能。
→(...)をつかって複数の要素をまとめて取り出す。
const drinks =[
"latte",
"coffee",
"water"
];
//一つ取り出す(旧)
var clear = drinks[2];
//二番目以降取り出す(slice()を使う)
var delisiousDrinks = drinks.slice(1);
//まとめて取り出す(新)
const [drink1,drink2,drink3] = drinks;
//二つ目以降要素まとめて取り出す
const[,...other] = drinks;
配列の加工
スプレッド構文を使って配列の加工をする
スプレッド構文:先程の(...)を用いた構文
const pencase:string[] = [
"pen",
"eraser",
"namepen"
];
const wantedItem = [
"ruler",
"redpen",
"bluepen"
];
//ペンを捨てて定規と赤青ペンを入れる
const [pencase(1),pencase(2)] = tidiedPencase;
const newPencilCase = [...tydiedPencase, ...wanterItem];
//スプレッド構文で配列のコピー
const copy = [...pencase];
配列のソート
ソート:配列のインデックスを並び替える
const numbers = [30, 1, 200];
numbers.sort();
// 1, 200, 30
ループ文はfor...ofを使う
ループの書き方3つ
・for文
・forEach()
・for...of
var iterable = ["小金井", "小淵沢", "小矢部"];
// 旧: C言語由来のループ
for (var i = 0; i < iterable.length; i++) {
var value = iterable[i];
console.log(value);
}
// 中: forEach()ループ
iterable.forEach(value => {
console.log(value);
});
// 新: for ofループで配列のインデックスが欲しい
for (const [i, value] of iterable.entries()) {
console.log(i, value);
}
// 要素のみ欲しいときは for (const value of iterable)
イテレータ
イテレータ:「イテラブル」なオブジェクトから生成されるオブジェクトで、「イテレータリザルト」を返します。またnext()という関数を持つオブジェクトです
type Hoge = {
value: string;
done: boolean;
}
type HogeIterator = {
next: () => Hoge;
}
// hogeIteratorはイテレータ
const hogeIterator: HogeIterator = {
next : () => {
return { value: 'hogehoge', done: false }
}
イテレータリザルト:イテレータリザルトとは、値を表すvalueとイテレータが完了したかどうかを表すdoneという2種類のプロパティを持つオブジェクトのこと
type Hoge = {
value: string;
done: boolean;
}
// hogeはイテレータリザルト
const hoge: Hoge = {
value: 'hogehoge',
done: false,
}
読み込み専用配列
TypeScriptの「const」は変数の再代入をさせないが、「変更不可」にはできません。
TypeScriptにはこれには別のキーワード、readonlyが提供されています。型の定義の前にreadonlyを付与するか、リテラルの後ろにas constをつけると読み込み専用になります。
// 型につける場合はreadonly
const a: readonly number[] = [1, 2, 3];
// 値やリテラルに付ける場合はas const
const b = [1, 2, 3] as const;
a[0] = 1;
// Index signature in type 'readonly number[]' only permits reading.
オブジェクト
オブジェクト:JavaScriptのコアとなるデータですが、クラスなどを定義しないで、気軽にまとまったデータを扱うときに使う。
配列は要素へのアクセス方法がインデックス(数値)だが、オブジェクトの場合は文字列。
JSON
オブジェクトがよく出てくる。データ交換用フォーマットで文字列。
JSONはJS,TSに比べてルールが厳密。たとえばキーは必ずダブルクォーテーションで括るなど。
// 最初の引数にオブジェクトや配列、文字列などを入れる
// 2つめの引数はデータ変換をしたいときの変換関数(ログ出力からパスワードをマスクしたいなど)
// 省略可能。通常はnull
// 3つめは配列やオブジェクトでインデントするときのインデント幅
// 省略可能。省略すると改行なしの1行で出力される
const json = JSON.stringfy(smallAnimal, null, 2);
// これは複製されて出てくるので、元のsmallAnimalとは別物
const smallAnimal2 = JSON.parse(json);
基本的な構文
switch
switch (task) {
case "休憩中":
console.log("サーフィンに行く");
break;
case "デスマ中":
console.log("睡眠時間を確保する");
break;
default:
console.log("出勤する");
}
()とcaseが===で結ばれる時breakまでの処理を行う
基本的な型付け
一番手抜き型付け:any
anyと書けば、TypeScriptのコンパイラは、その変数のチェックをすべて放棄する。
使う場面
①ユーザー定義の型ガードの引数
②メインの引数ではなくて、挙動をコントロールするオプションの項目がかなり複雑で、型定義が複雑な場合
ユーティリティ型
ユーティリティ型(utility type)は、型から別の型を導き出してくれる型
Required
全プロパティを必須にする
Readonly
全プロパティを読み取り専用にする
Partial
全プロパティをオプショナルにする
Record
キー・バリューからオブジェクト型を作る
Pick
任意のプロパティだけを持つオブジェクト型を作る
Omit
任意のプロパティを除いたオブジェクト型を作る
などなど
タグ付き合併型
分岐して細かく型を設定できる感じ
type NumberStyle = {
color: string;
}
type NumberColumn = {
columnType: 'number';
caption: string;
field: string;
style: NumberStyle;
}
タグですぐに判断できる
type CheckStyle = {
uncheckBgColor: string;
checkBgColor: string;
}
type CheckColumn = {
columnType: 'check';
caption: string;
field: string;
style: CheckStyle;
}
type NumberStyle = {
color: string;
}
type NumberColumn = {
columnType: 'number';
caption: string;
field: string;
style: NumberStyle;
}
型ガード
型ガード:複数の型付けがされている時にこっちのパターンの型に対するロジックを書く時につかうもの
// userNameOrIdは文字列か数値
let userNameOrId: string|number = getUser();
if (typeof userNameOrId === "string") {
// このif文の中では、userNameOrIdは文字列型として扱われる
this.setState({
userName: userNameOrId.toUpperCase()
});
} else {
// このif文の中では、userNameOrIdは数値型として扱われる
const user = this.repository.findUserByID(userNameOrId);
this.setState({
userName: user.getName()
});
}
組み込み型ガード
・typeof
・instanceof
・in
・比較
主にこの4つ
①typeof 変数
→変数の型名を文字列で返してくれる
undefined: "undefined"
bool型: "boolean"
数値: "number"
文字列: "string"
シンボル: "symbol"
関数: "function"
この他のものは"object"として返す
②変数 instanceof クラス名
→自作のクラスで使える
③"キー" in オブジェクト
→オブジェクトに特定の属性が含まれているかどうかの判定
型アサーション
キャスト=型アサーション
型アサーション:コンパイラのもつ型情報を上書きすること
const page: any = { name: "profile page" };
// any型からはasでどんな型にも変換できる
const name: string = page as string;
ただし基本的にasは使わないし、anyも使わない。今回もpageはstringでないからコンパイラでエラーは吐かないが、ページでエラーをはく
関数
関数:一連の処理に名前をつけたもの
ネスト:あるものの中に、それと同じ形や種類の(一回り小さい)ものが入っている状態や構造(ex:if( 条件A ){ ... if( 条件B ){ ... } ... } )
function 関数名(引数リスト): 返り値の型 {
return 返り値
}
引数はカンマで区切る、引数の型付けもする。
typescriptの関数の特徴
関数そのものを変数に入れて名前をつけられるし、データ構造にも組み込める
他の関数の引数に関数を渡せる
関数の返り値として返すことができる
関数のバリエーション
無名関数(アノニマス関数):名前がない
クロージャ:関数内に作られた関数
メソッド:何かオブジェクトに属する関数
非同期関数:処理全てが終わる前に何か他の処理を行うことのできる関数
関数の引数と返り値の型定義
// 昔からあるfunctionの引数に型付け。書く引数の後ろに型を書く。
// 返り値は引数リストの () の後に書く。
function checkFlag(flag: boolean): string {
console.log(flag);
return "check done";
}
// アロー関数も同様
const normalize = (input: string): string => {
return input.toLowerCase();
}
具体的には
function 関数名(仮引数:データ型):返り値のデータ型 {
処理;
}
アロー関数の場合
const 変数 =(引数:データ型):返り値の型 =>{
処理;
}
型が明確な場合は書かなくてもよい
関数が何も帰さない場合:voidをつける
複数の型決めはあまりよろしくない
関数を扱う変数の型定義
ex)文字列と数値を受け取ってbooleanを返す関数
let check:(arg1:string,arg2:number) =>boolean;
ここでは返り値は=>の右側につけて{}ははずす。
ex)arg2がもし関数であったとき
let check (arg1:string arg2:(arg3:string)=>number) =>boolean;
sortに関する注意
jsとTSで違いがあるので注意
SortSample.js
const array = [1,5,2,4,3];
array.sort();
console.log(array);
/*
- 結果
- 「1,2,3,4,5」
- (期待通りに並べ替えが発生する)
*/
jsは戻り値がソートされた配列、対象の配列上で直接行われる。array自体の配列の中身が入れ替わる。
それに対してtypescriptは
SortSample.ts
let array = [1,5,2,4,3];
array = array.sort();
console.log(array);
/*
- 結果
- 「1,2,3,4,5」
- (期待通りに並べ替えが発生する)
*/
sortされた結果を戻り値として返却するのでarrayの並びを直接入れ替えることはないので太字のようにarrayを新しく定義する必要がある
sortの比較
・compareFunction(a,b)が未満の時aをbよりも小さいインデックスにソートする(=配列でaが先に来る)
・compareFunction(a, b) が 0 より大きい場合、b を a より小さいインデックスにソートします。(=b が先に来るようにします)
compareFunction(a, b) が 0 を返した場合、a と b は互いに変更せず、他のすべての要素に対してソートします。
function compare(a, b) {
if (ある順序の基準において a が b より小) {
return -1;
}
if (その順序の基準において a が b より大) {
return 1;
}
// a は b と等しいはず
return 0;
}
こんな感じで比較、並び替えを行う
function sort(a: string[], conv: (value: string) => string) {
const entries = a.map((value) => [value, conv(value)])
entries.sort((a, b) => {
if (a[1] > b[1]) {
return 1;
} else if (a[1] < b[1]) {
return -1;
}
return 0;
});
return entries.map(entry => entry[0]);
}
const a: string[] = ["a", "B", "D", "c"];
console.log(sort(a, s => s.toLowerCase()))
// ["a", "B", "c", "D"]
アロー関数のバリエーション
// 基本形
(arg1, arg2) => { /* 式 */ };
// 引数が1つの場合は引数のカッコを省略できる
// ただし型を書くとエラーになる
arg1 => { /* 式 */ };
// 引数が0の場合はカッコが必要
() => { /* 式 */ };
// 式の { } を省略すると、式の結果が return される
arg => arg * 2;
// { } をつける場合は、値を返すときは return を書かなければならない
arg => {
return arg * 2;
};
引数が一つの場合や式の結果をそのままreturnする場合に括弧を省略できる。
非同期処理
コールバック関数:時間のかかる処理を行った後に実行する関数
非同期処理の歴史
コールバック地獄→
Promiseの登場(1段のネストで済む)、then()節の利用
→「await」の使用
// 新: 非同期処理をawaitで待つ(ただし、awaitはasync関数の中でのみ有効)
const resp = await fetch(url);
const json = await resp.json();
console.log(json);
await を扱うにはasyncをつけて定義された関数でなければなりません。 TypeScriptでは、 async を返す関数の返り値は必ず Promise になります。 ジェネリクスのパラメータとして、返り値の型を設定します。
async function(): Promise {
await 時間のかかる処理();
return 10;
}
注意
比較的新しく作られたライブラリではpromiseを返す仕様になっているがそうでないコールバック関数方式のコードを使う場合「new Promise」を使う
// setTimeoutは最初がコールバックという変態仕様なので仕方なくnew Promise
const sleep = async (time: number): Promise => {
return new Promise(resolve => {
setTimeout(()=> {
resolve(time);
}, time);
});
};
await sleep(100);
非同期と制御構文
「Promise」ってなんだっけ
一連の流れ
ex:電気屋へ修理
修理の依頼(Promise)→修理できた(resolve)→次の処理(支払い)へ(Promise)
修理の依頼(Promise)→修理できない(reject)→エラー処理へ(catch)
.js
const repairPromise = new Promise((resolve, reject) => {
const repair = true;
if(!repair) reject('修理してください');
return setTimeout(() => resolve('修理しました'), 3000);
});
const paymentPromise = new Promise((resolve, reject) => {
const payment = true;
if(!payment) reject('送金まだですか?');
return setTimeout(() => resolve('送金しました'), 500);
});
console.log('進捗どうですか?')
repairPromise
.then(res => {
console.log(res);
return paymentPromise.then(res => console.log(res)).catch(err => console.log(err));
})
.catch(err => console.log('errorめっせー', err));
宣言した処理が完遂するとthenで実行する
通常のasync/awaitの場合
.js
const asyncFunc = async() => {
console.log('進捗どうですか');
try{
const msg1 = await repairAsync(3000);
console.log(msg1);
const msg2 = await paymentAsync(500);
console.log(msg2);
} catch(e) {
console.log(e);
}
};
const repairAsync = (ms) => new Promise(resolve => {
setTimeout(() => {
resolve('修理しました')
},ms);
});
const paymentAsync = (ms) => new Promise(resolve => {
setTimeout(() => {
resolve('送金しました')
},ms);
});
asyncFunc();
一つ目のawaitが終わるまでに二つ目のawait処理を進められない
ts.
const asyncFunc = async(): Promise => {
console.log("進捗どうですか");
try {
const msg1 = await repairAsync(3000);
console.log(msg1);
const msg2 = await paymentAsync(500);
console.log(msg2);
} catch (e) {
console.log(e);
}
};
const repairAsync = (ms: number): Promise =>
new Promise((resolve) => {
setTimeout(() => {
resolve("修理しました");
}, ms);
});
const paymentAsync = (ms: number): Promise =>
new Promise((resolve) => {
setTimeout(() => {
resolve("送金しました");
}, ms);
});
asyncFunc();
イメージ
大本asyncFunc(promise):非同期関数
内容はtryとcatch
大本のpromiseの中でawaitによってnew promiseの関数をそとで定義されてるところから呼び出す
ex:味噌汁を温めながらご飯を電子レンジで温めて、温め終わったら両方食べる
async function 味噌汁温め(): Promise<味噌汁> {
await ガスレンジ();
return new 味噌汁();
}
async function ご飯温め(): Promise<ご飯> {
await 電子レンジ();
return new ご飯();
}
const [a味噌汁, aご飯] = await Promise.all([味噌汁温め(), ご飯温め()]);
いただきます(a味噌汁, aご飯);
非同期で繰り返し呼ばれる処理
async/awaitは便利なものですが、ワンショットで終わるイベント向けです。繰り返し行われるイベント(addEventListener()を使うようなスクロールイベントとか、画面のリサイズsetInterval()の繰り返しタイマー)に対しては引き続きコールバック関数を登録して使います
addEventListener:イベントの実行、処理を行うためのメソッド
ex)
対象要素.addEventListener( 種類, 関数, false )
種類はネットで検索する!いっぱい載ってる
関数は無名関数or外部で定義した関数orアロー関数
無名関数の場合
対象要素.addEventListener(種類, function() {
//ここに処理を記述する
}, false);
アロー関数の場合
対象要素.addEventListener(種類, () => {
//ここに処理を記述する
});
setInterval():処理をxミリ秒後に繰り返し行うためのメソッド
let count = 0;
const countUp = () => {
console.log(count++);
}
setInterval(countUp, 1000);
関数のcountUpを1000ミリ秒(1秒)後に再び行う
例外処理
例外処理とは
A→B→Cと順番にタスクをこなす際に例えばデータの取得がうまくいかなかったり、データの送信がうまくいかない際に処理を中断する(例外を投げる),中断したことを察知して何かしらの対処(
回復処理を行うこと。
throwを使って例外処理を投げる。throwするとその行でその関数の処理が中断し、呼び出し元へ巻き戻る。巻き戻った先にあるtry節/catch節のペアに当たるまで戻る。
ex)
throw new Error("ネットワークアクセス失敗");
console.log("この行は実行されない");
例外を投げる処理の周りはtry節で囲む
catchは例外が飛んできたときに呼ばれるコードブロック
finallyは例外が発生してもしなくても必ず通る
ex)
try {
const data = await getData();
const modified = modify(data);
await sendData(modified);
} catch (e) {
console.log(エラー発生 ${e}
);
throw e; // 再度投げる
} finally {
// 最後に必ず呼ばれる
}
もし、回復処理で回復し切れない場合は、再度例外を投げることもできます。
Errorクラス
問題が発生したときに情報伝達に使うのがErrorクラスでふつうのオブジェクト
Errorクラスは作成時にメッセージの文字列を受け取れる。name属性にはクラス、massageにはコンストラクタに渡した文字列が格納される。
処理系独自の機能でstackプロパティに格納されるスタックトレースはthrowした関数が今までどのように呼ばれてきたかのりれきである。デバックのどに使う。
try節はなるべく狭くする
ex)before
try {
logicA();
logicB();
logicC();
logicD();
logicE();
} catch (e) {
// エラー処理
}
ex)after
logicA();
logicB();
try {
logicC();
} catch (e) {
// エラー処理
}
logicD();
logicE();
tryの範囲を狭めることでどこで何が起きているのか分かりやすくなる
原因の違う例外が投げられることで混ざってしまう可能性もある。
Error以外をthrowしない
下のコードではcatch節の中でeのデータ型がError前提で書かれておりコードの補完が効くのでthrowではErrorしか投げない
try {
:
} catch (e) {
// e.とタイプすると、name, messageなどがサジェストされる
console.log(e.name);
}
リカバリー処理の分岐のためにユーザー定義の例外クラスを作る
コンストラクタ:クラスをnewした瞬間に実行される関数
クラス:設計図
インスタンス:設計図を基に作った実際のもの
オブジェクト:モノ(クラスとかインスタンスとかふんわり表現したもの)
例外処理のためにクラスを作っておく。さまざまなシチュエーションでクラスの継承を行い対応する。
// 共通エラークラス
class BaseError extends Error {
constructor(e?: string) {
super(e);
this.name = new.target.name;
// 下記の行はTypeScriptの出力ターゲットがES2015より古い場合(ES3, ES5)のみ必要
Object.setPrototypeOf(this, new.target.prototype);
}
}
// BaseErrorを継承して、新しいエラーを作る
// statusCode属性にHTTPのステータスコードが格納できるように
class NetworkAccessError extends BaseError {
constructor(public statusCode: number, e?: string) {
super(e);
}
}
// 追加の属性がなければ、コンストラクタも定義不要
class NoNetworkError extends BaseError {}
例外を受け取ったcatch節でリカバリー方法を選ぶことができる。その際に「instanceof」を使用する。instanceofは型ガードになっているのでコードの補完が行われる。
try {
await getUser();
} catch (e) {
if (e instanceof NoNetworkError) {
alert("ネットワークがありません");
} else if (e instanceof NetworkAccessError) {
// この節では、eはNetworkAccessErrorのインスタンスなので、
// ↓のe.をタイプすると、statusCodeがサジェストされる
if (e.statusCode < 500) {
alert("プログラムにバグがあります");
} else {
alert("サーバーエラー");
}
}
}
非同期と例外処理
promise→
①then()の二つ目のコールバック関数でエラー処理を行う
②catch()節内にエラー処理を書く
ex)promiseのエラーの書き方
fetch(url).then(resp => {
return resp.json();
}).then(json => {
console.log(json);
}).catch(e => {
console.log("エラー発生!");
console.log(e);
});
async関数→
①try節内でawaitしてエラーを捕まえる
try {
const resp = await fetch(url);
const json = await resp.json();
console.log(json);
} catch (e) {
console.log("エラー発生!");
console.log(e);
}
②promise作成時のコールバック関数の二つ目の引数のreject()コールバック関数にオブジェクトを渡す。
async function heavyTask() {
return new Promise((resolve, reject) => {
// 何かしらの処理
reject(error);
// こちらでもPromiseのエラーを発生可能
throw new Error();
});
};
モジュール
パッケージとは
Node.jsを核とするJS,TS共栄圏の言葉。
Node.jsが配布するソフトウェアの塊の単位。
nmpやyarnなどのツールを使ってnpmjs.orgなどのリポジトリからダウンロードすることができる。
ブラウザ向けのフレームワークなどもいまはnpmjs.orgで配布される。
パッケージのダウンロード
$ npm install @vue/cli vue
vueを作成するCLIコマンドとライブラリの二つをダウンロード
モジュールとは
JS,TS界隈でモジュールというとTS/JSの一つのソースファイルのことを指す。簡単に言えば.ts,.jsのファイルがモジュール。パッケージ内に大量のモジュールが入るイメージ。パッケージ作成時に1つ代表となるモジュールを決める(main属性)
TSでモジュールになるもの
・TypeScriptの1ファイル
・TypeScript用の型定義ファイル付きのnpmパッケージ
・TypeScript用の型定義ファイルなしのnpmパッケージ+TypeScript用の型定義ファイルパッケージ
エクスポート
エクスポートとは
ファイル内の変数、関数、クラスを送り出す
// 変数、関数、クラスのエクスポート
export const favorite = "小籠包";
export function fortune() {
const i = Math.floor(Math.random() * 2);
return ["小吉", "大凶"][i];
}
export class SmallAnimal {
}
インポートとは
エクスポートしたものはimportを使って取り組む。名前がぶつかりそうなときはasを使って別名をつけることができる。
// 名前を指定してimport
import { favorite, fortune, SmallAnimal } from "./smallanimal";
// リネーム
import { favorite as favoriteFood } from "./smallanimal";
defaultエクスポートとインポート
エクスポートする要素の1つを default の要素として設定できます。
// defaultをつけて好きな要素をexport
export default address = "小岩井";
// defaultつきの要素を利用する時は好きな変数名を設定してimport
// ここではlocationという名前でaddressを利用する
import location from "./smallanimal";
default のエクスポートと、 default 以外のエクスポートは両立できます
// defaultつきと、それ以外を同時にimport
import location, { SmallAnimal } from "./smallanimal";
パスの書き方-相対パスと絶対パス
相対パス:ピリオドから始まる、import文がかかれたファイルのフォルダを起点に探す
絶対パス:ピリオド以外から始まる。検索アルゴリズムを使って探す
ひとつがtsconfig.jsonの compilerOptions.baseDir です。 プロジェクトのフォルダのトップを設定しておけば、絶対パスで記述できます。 プロジェクトのファイルは相対パスでも指定できるので、どちらを使うかは好みの問題ですが、Visual Studio Codeは絶対パスで補完を行うようです。
動的インポート
初期ロード時間を減らしたいときに使うのは動的インポート。Promiseを返すimport()関数となっている。fileアクセスやネットワークアクセスをしてファイルを読み込みロードが完了すると解決する。
ジェネリクス
ジェネリクスとは
ジェネリクスとは日本語で総称型と呼ばれる、使われるまで型が決まらないようないろいろな方を受ける機能を作るときに使う。
ジェネリクスの書き方
ジェネリクスは関数、インターフェース、クラスなどと一緒に利用できる
ジェネリクスの場合は名前の直後、関数の場合は引数リストの直前にジェネリクス型パラメータを関数の引数のように記述する
下のコードでは「T」がそれにあたる
function multiply(value: T, n: number): Array {
const result: Array = [];
result.length = n;
result.fill(value);
return result;
}
T には string など、利用時に自由に型を入れることができます。宣言文と同じように < > で括られている中に型名を明示的に書くことで指定できます
// -1が10個入った配列を作る
const values = multiply(-1, 10);
// ジェネリクスの型も推論ができるので、引数から明示的にわかる場合は省略可能
const values = multiply("すごい!", 10);
ジェネリクスの引数名にはT,U,Vなどがつかわれる。
preventDefault()について
①イベント
DOM内の各要素では頻繁に「イベント」が発生
A,ユーザーが発生させるイベント、B,ブラウザが勝手に発生させるイベント
A,ユーザーが発動させるイベントの例
・click PCでは頻繁に発生させています
・keypress キー入力の際に発生するイベントです
・touchmove スマホを使っている人は日常的に大量に発動させています
B.ブラウザが勝手に発動させるイベントの例
・DOMContentLoaded ブラウザによりHTMLの解析が完了した場合に勝手に発動します
・ended 見慣れないかもしれませんが、audioやvideoが再生終了したときに勝手に発動します。
・error よく見ますよね。通信エラーやJavaScriptエラーが発生した際に勝手に発動します。
②イベントのデフォルト動作例
イベントのデフォルト動作例
イベント | デフォルト動作例 |
---|---|
「touchmove」 | スマホの画面がスクロールされる |
aタグ」での「click」 | aタグのherfで指定されたURLへ遷移する |
「formのチェックボックス」での「click」 | チェックボックスのオン/オフが切り替わる |
テキストタイプの「form」での「keypress」 | 文字が入力される |
inputの「submit」での「click」 | actionで指定されたURLへ遷移+データ送信 |