モジュール
パッケージ
ソフトウェアの最小単位の塊。package.jsonのdependeciesに記載されているやつ
モジュール
一般的にTypescript/Javascriptの1つのソースファイルを指す(.ts/.js)。パッケージ⊃モジュール。 バンドラー(webpackなど)を使用すると、import/exportを解析して単一のjsファイルを生成する場合がある。
export/import
export キーワードをつけると他のファイルから利用ができるようになる。 defaultキーワードをつけると、import時に自動で読み込まれる要素を選択することができる。
export const favorite = "小籠包"; export default name = "hoge" export function fortune() { const i = Math.floor(Math.random() * 2); return ["小吉", "大凶"][i]; } export class SmallAnimal { }
import キーワードで取り込みたい要素を選択する。
// 名前を指定してimport import { favorite, fortune, SmallAnimal } from "./smallanimal"; // リネーム import { favorite as favoriteFood } from "./smallanimal"; //defaultを指定している場合、hogeがdefault要素になる。 import hoge from "./smallanimal";
importパス
動的import
import/exportはコード実行時に全て解決している前提で処理される。しかし、起動を早くしたい場合動的にimportを行うことができる。
Promiseを返すimport()関数を利用する。(ES2018以降有効)
必要なタイミングで、const module = await import('./utils/create-zip-file');
みたいに書けばよい。
まとめてexport
エントリーポイントとなるスクリプトに公開要素を1つのファイルにまとめることができる。 partA-C 3つのファイルに分けて、1つのファイルでまとめて公開する。
export {ele1, ele2} from "./partA"; export {ele3 as mainEle} from "./partB"; export {ele4 as default} from "./partC";
自動でimport
tsconfig.jsonのcompilerOptions.types
で自動importするモジュールを指定できる。なんかよくわからないモジュールがあったら、ここから呼ばれているかも。
tsconfigのmodule
CommonJSとの違いの章でそういやCommonJSってなんだという感じになって調べてみた。 下記が分かりやすかった。 https://zenn.dev/naoki_mochizuki/articles/46928ccb420ee733f78f
javascriptには仕様が乱立してて、typescriptのコンパイル後にどの仕様にあわせて変換するかをtsconfig.jsのmoduleで選択できる。仕様の違いの一つにimport/exportの方法がある。 CommonJSの方法でもモジュールの読み込みなどを書くことはできるっぽいが、特に利点はないので気にしない。
console.log
console.log({object})
でオブジェクトのキーと値が出力される。
console.tableでテーブル形式で表示される。 console.dirというツリー構造で表示する出力もあるが、Node.jsではサポートされていない。(console.logと同じ扱い。ブラウザの開発者ツールだとツリー形式で表示される。)
const ob = { test: "hoge", hoge: "muge" } console.table({ob}); ┌─────────┬────────┬────────┐ │ (index) │ test │ hoge │ ├─────────┼────────┼────────┤ │ ob │ 'hoge' │ 'muge' │ └─────────┴────────┴────────┘
ジェネリクス
基本Javaと同じ
パラメータ制約もextendsでつけれる。型推論が効く。
function multiply<T>(value: T, n:number): Array<T> { const result: Array<T> = []; result.length = n; result.fill(value); return result; } //引数で型が分かるので、省略可 const value = multiply(-1, 10); const hoge = multiply<string>("number", 10); console.table(value); console.table(hoge);
extends
type Person = { getBirthDay(): Date; } function isTodayBirthday<T extends Person>(person: T): boolean { const today = new Date(); // person の型は少なくともPerson を満たす型なのでgetBirthDay() メソッドが利用可能 const birthDay = person.getBirthDay(); return today.getMonth() === birthDay.getMonth() && today.getDate() === birthDay. getDate(); } const p:Person = { getBirthDay: ()=> { return new Date("2020-01-01"); } } const r = isTodayBirthday(p); console.log(r);
下記のような型パラメータもおk。Tが決まれば、Kも決まる。T/Kが決まればUが決まるので全部解決可能。
- T
- オブジェクトの型
- K
- Tオブジェクトのプロパティ名の合併型
- keyof T -> "Tプロパティ1" | "Tプロパティ2" | "Tプロパティ3"
- Tオブジェクトのプロパティ名の合併型
- U
- オブジェクトのプロパティの型
function setValue<T, K extends keyof T, U extends T[K]>(obj: T, key: K, value: U) { obj[key] = value; } type ParkForm = { name:string, hasTako:boolean } const park: ParkForm = { name: "恵比寿東", hasTako: true }; console.table({park}); setValue(park, "name", "神明児童遊園"); console.table({park});
オブジェクトに対するユーティリティ型がいくつか用意されている。オブジェクトのプロパティを必須にしたり、省略可能にしたりできる。下記一例。
type User = { name: string, organization:string; } const u:User = { name: "u", organization: "unknown" } //プロパティが省略可能に const uPratial: Partial<User> = { name: "u" } type Client = { name?: string, organization?:string; } const c:Client = {} //プロパティが必須に const uRequired: Required<Client> = { name: "hoge", organization: "fuga" } //undefinedが抜ける type year = NonNullable<string | number | undefined> //重複した方が抜ける type typeString = Exclude<string | number | boolean, number| boolean> //重複した型が選択される type typeNumber = Extract<string | number, number| boolean>
any/unkown
any/unkownを使用すると型情報がリセットされる。可能ならジェネリクスを使った方が良い。
一通り読み終わった。あまり目新しい機能はなかったけど、ジェネリクスで型を操作したり、プロパティの属性を操作したりするユーティリティは勉強になった。あまり使いどころが分からないが...