備忘録
説明がわかりやすく、
jsの復習にもなってちょうどよかった。
わからなかった、知らなかったことだけ↓
1章
関数オーバーローディング
異なるシグネチャの関数を複数定義できる
2章
式と文
結果が伴うものを式。
文は宣言(let.const)とその他に分けられる。
例)const a = "hello";
上記の例では全体では文、「”hello”」の箇所は式である。
関数呼び出し(console.logなど)は式に分類される。(すべて返り値という結果を持つため)
式のあとにセミコロンを書く式を式文と呼ぶ。
結果がいらない式を実行する文といえる。
例)console.log();
// Number(str)でなくこんな書き方もできるよ
let str:string = '123';
+str * 100 = 12300;
x === null || x === undefined
// 以下のようにかける
x == null
比較演算子ではNaNが入るといかなる場合でもfalseになる。
例)x = NaN x === NaN //これはfalse
// プリミティブの真偽をBoolean(x)でなく以下のようにかける
const x = 123;
console.log(!!x) // true
// ?? は左辺がnullまたはundefinedのときだけ右辺を返す
// || と ?? の違い
"" || 関数とか // 右辺実行
"" ?? 関数とか // 左辺実行
3章 オブジェクト
const obj = {...}
{}はオブジェクトリテラル。オブジェクトリテラルは式。
key: 値 は
プロパティ名:式
ネストされたスプレット構文について
スプレット記法を使う方法はあくまで「各プロパティが同じ値を持つ新しいオブジェクトを作る」というもので、プロパティの中にオブジェクトが入っている場合は同じオブジェクトのまま。
const foo = { obj : { num : 124 } };
const bar = { ...foo }
この時、objは別だが、{ num:124 }にたいしては同じ参照
type文 interface宣言
type文では任意の型に別名を宣言できたが、interfaceはオブジェクト型だけ。
宣言マージだけinterface宣言が行える。基本的にtype文を使う。
インデックスシグネチャ
任意のプロパティ名を受け入れる型。
一般に非推奨。Mapオブジェクトで代替する。
オプショナルなプロパティの宣言
?つけるやつ。正体はユニオン型。
baz?: boolean;
読み取り専用 readonly
オブジェクトの再代入を防ぐ事ができる。
変数の型を取得できるtypeof
明示されてないオブジェクトからでも型推論によりtypeofで取得できる。
一般に濫用すべきでない。
部分型(TSでは構造的部分型)
type FooBar = { foo: string; bar: number; }; type FooBarBaz = { foo: string; bar: number; baz: boolean; };
FooBarBazはFooBarの部分型である。
FooBarを満たす条件はFooBarBazを必ず満たす。
オブジェクトみたいに考えていると逆じゃねって思っちゃう。
S extends T という構文が度々登場するが、これはSはTの部分型であるということ。
型引数 - ジェネリック型
型引数を<>で囲って型引数を宣言する
type User<T> = {
name: string;
type: T
}
また、extendsも使うと部分型であることを宣言し、
= を使うとオプショナルな型引数であることを宣言する
配列の型
T[], または Array<T>
タプル型
[number,string]のように配列の数と型の順番を指定できる
分割代入
分割代入では型注釈を与えることができない。型推論となる。
restパターン
const{ foo, ...rest } = obj;
とすると、obj.fooはfooに、のこりのプロパティをrestに代入する
プログラミングを習得するというのはオブジェクトの使い方を暗記するということではなく、必要に応じて自分で調べられるだけの基礎知識をつけるということなのです
組み込みオブジェクト
・Dateオブジェクト
・正規表現オブジェクト
・Map/Setオブジェクト
Map/Setと違い、WeekMap/WeekSetはガベージコレクションの対象となるらしい
legthなど、stringのプリミティブなのにプロパティがあるような挙動がある。
これはプリミティブに対してプロパティアクセスを行う際に一時的にオブジェクトが作られているらしい
4章 関数
関数型
type F = (arg: string) => string
※型にかく引数名は実際の引数名と違ってもエラーにならない
返り値のない関数 => void
データとんだ
データめちゃとんだ
5章 クラス
readonly
class User {
readonly name: string;
静的プロパティ・静的メソッド
クラスそのものに属するプロパティ・メソッド
クラスがオブジェクトみたいに、プロパティを持つ的な
あまり使わないかも
アクセシビリティ修飾子 public, protected, private
どこからアクセスできるかを決定する
何も書かないとpublicと同じ。
privateを書くとクラス内でしかアクセスできなくなる。外からconsole.logとかも直接だと無理。
#をつけてもprivateと同じ挙動をする。(#のほうがjavascriptの機能で、最近できた機能。厳密。)
protectedは継承時にそのクラスを継承する子クラスからもアクセスできるよということ。
プロパティ宣言の省略(typescript固有)
class User {
constructor(public name: string, private age: number) {}
}
constructorの中の this.age = age; this.age = age;もいらない
クラスの型
クラス宣言でUserというクラスを作成したら同時にUser型も作成される
newシグネチャ
type ExampleType = {
new (): User;
}
コールシグネチャと同様にプロパティやメソッドを持つというオブジェクトを表現したいときに使える
クラスの場合プロパティ・メソッドが該当するため、コールシグネチャよりも使い道があるかも
継承
Aを継承してBを作った場合、BはAの機能をすべて持っているので、BはAの部分型となる。
継承を用いることで、あるクラスの部分型となる別のクラスを作ることができる
オーバーライドされたプロパティやメソッドはoverride修飾子をつけることができる。つけなくても機能するが、バグを産まないためにつけたほうがいいかも。(tsconfig.jsonのnoImplicitOverrideで必須にできる)
Implementsキーワードによる追加の型チェック
class クラス名 implements 型 でクラスが型の部分型であることを宣言する
アロー関数のthis
アロー関数は自分自身のthisをもたない。外側の関数のthisを受け継いでいる。
例外処理
大域脱出・・・実行を中断して別の場所にプログラムの制御を移すこと
try-catch文
6章 高度な型
ユニオン型/インターセクション型
| / &
age?: numberは age?: number | undefined であって age: number | undefined ではない
オプショナルチェイニング
プロパティアクセス/関数呼び出し/メソッド呼び出し
obj?.foo["bar"]().baz().hoge
これはエラーにならない。objがundefinedならそれ以降はすべて飛ばす。
リテラル型
ユニオン型で頻出
リテラル型のwidening
case1
const name1 = 'a';
let name2 = 'b';
このときconstはリテラル型'a'だが、letの方はプリミティブ型stringになる。
case2
{name: "matsu"; age: 26}のとき、{name:string; age:number}である。
オブジェクトリテラルの型が推論される時、各プロパティの型がリテラル型となる場合はwideningされる。
両caseともにあとから上書きされることが予想されるから
オブジェクトをwideningさせたくないときの対処法
readonlyをつける
as const を使う
型の絞り込み=コントロールフロー解析
条件分岐の条件を見て、位置に応じて型が変化する。(vscodeで型にマウスを乗せる)
TypeScriptの標準テクニック- 代数的データ型(ADT)をユニオン型で再現する
ユニオン型の構成要素であるオブジェクト型のそれぞれに”タグ”となるプロパティを付け加え、扱うデータの形と可能性を型で正確に表現する。
type や tag などのリテラル型を加える。
疑似ADTを使う場合switch文のほうが一般に有利。
lookup型、keyof型
lookup型 T[K]
オブジェクト型TのKプロパティの型
目的:同じことを2度書かない→型情報を再利用でき、変更に強い
keyof型 keyof T
オブジェクト型からそのオブジェクトのプロパティ名の型を得る機能。文字列のリテラル型を取れる
オブジェクトの型をtypeofでとって keyof typeof オブジェクト という使い方もできる
as による型アサーション
できるだけ避けるべき
型をこちらで決定付けしてしまう assertion: 断言、主張
同じように ! でnullとundefinedを無視するのも危険
as const の用法
型アサーションと違い危険でない。安全性を高めてくれる機能
const name1 = ["ha", 'yu', 'ioui']; // string[]
const name2 = ["ha", 'yu', 'ioui'] as const; // readonly ["ha","yu","ioui"]
type Name = (typeof name2)[number];
とにかく避ける any型 と、 似てるが安全なunknown型
両者の区別つけれるようになろう
any型は型チェックを無効化する型
asによる型アノテーションのほうがまし。
asを適切に使えばanyの使用はまったく不要。
unknown型はなんでも入れられる型。
TypeScriptコンパイラは、unknown型の値は不明のため、できることを限定してくれる。
typeof,if,switchや、ユーザー定義型カードで型の絞り込みを行おう
object型・never型
object型はプリミティブ以外すべてを表す型
never型はunknown型と逆で当てはまる値が存在しないという型
never型を受け取る関数が合った場合、その関数を呼び出すことは不可能。
never型はすべての型の部分型であると言える。
never型を返す関数は必ず例外を投げる関数
型述語(ユーザー定義型ガード)
型の絞り込みを自由に行うための仕組み
1,引数名 is 型
2,asserts 引数名 is 型
anyをつかうよりはas,asを使うよりはユーザー定義型ガード
if文の条件部分でユーザー定義型ガードを呼び出すことで、型述語に書かれた通りの絞り込みが行われる。
mapped types
{
[P in K]: T
}
conditional types
X extends Y ? S : T
型の条件分岐を行う。型レベルプログラミング。奥深い
上記から応用した組み込みの型
Readonly<T> ・・・Tのオブジェクト型のすべてのプロパティを読み取り専用(readonly)にしたオブジェクト型
Partial<T> ・・・Tのすべてのプロパティをオプショナルにした型
Required<T> ・・・Tのすべてのプロパティをオプショナルでなくした型
Pick<T,K> ・・・Tのオブジェクト型のうちKで指定した名前のプロパティのみを残したオブジェクト型
Omit<T,K> ・・・Kで指定されたプロパティを除いたオブジェクト型
Extract<T,U> ・・・Tの構成要素のうちUの部分型であるもののみを抜き出した新しいユニオン型を返す
Exclude<T,U> ・・・Tの構成要素のうちUの部分型であるもののみを取り除いた新しいユニオン型を返す
NonNullable<T> ・・・Tからnullとundefinedを除く (Exclude<T, null | undefined>)
7章 モジュールシステム
import/export
書き順がどうであれ、importされたファイルはimportするファイルより先に実行される
Node.jsの組み込みモジュール
nodejsに最初から備わっているモジュール
import文で./ や../で始まらずいきなりモジュール名が書かれているものは外部モジュールであるとみなされる
DefinitelyTypedと@types
npmで配布されているモジュールには、TypeScript向けの型定義が同梱されているものとそうでないものがある。
同梱されていないものはエラーが起きるが、@typesパッケージをインストールし解決する。
@typesパッケージの開発・運用はMicrosoftが運営するDefinitelyTypedというシステムに集約されている。
自分で型定義ファイルを作るには
自前の型定義は.d.tsファイルに書く。
8章 非同期処理
Node.jsはシングルスレッド。なのでノンブロッキングなAPIが基本的に用意されている。
非同期処理をTypeScriptプログラムから扱う方法のうち、最も原始的なものはコールバック関数
コールバック関数とは、非同期処理が終わった時点で呼び出される関数である
Node.jsでは原則としてコールバック関数の引数は1個めがエラー、2個めが内容/result
同期的な処理の実行中に非同期処理が割り込むことはない。
Promise
Promiseベースの非同期処理では、非同期処理を行う関数は関数を受け取らず、Promiseオブジェクトを返す。(同期処理)(この状態ではPromiseはまだ結果が決まっていない)(非同期に読み込みが開始される)(結果が返されるとthenメソッドのコールバックが呼び出される)
PromiseオブジェクトはPromise<T>という型を持つ。
Promiseの失敗時の処理を記述する際はanyに注意。unknown型にしよう。
new Promiseで作れる
thenの第2引数に失敗のコールバック関数
静的メソッド
・Promise.resolve
・Promise.reject
・Promise.all
・Promise.race
・Promise.allSettled
・Promise.any
Promiseチェーン
JavaScriptではPromiseがネストするということはない。「PromiseのPromise」はつくられない。
thenやcatchが新しいPromiseを生成する以上は、何もコールバック関数が登録されていないPromiseというのが必然的にある
dynamic import 構文
import("fs/promises").then(
モジュールが必要になるまでそのモジュールを読み込みたくない場合に
9章 コンパイラオプション
glopパターン
include / exclude ・・・含めたいファイルなど
strict ・・・型チェックの厳しさ