Closed7

📚 プログラミングTypeScript

Haruya IzumiHaruya Izumi

1ç«  むントロダクション

曎に詳しく芋るには...

TypeScriptの堎合だず

『テキスト゚ディタヌで入力した時』に゚ラヌメッセヌゞを䞎えおくれる。

3 + []
// ゚ラヌ TS2365: 挔算子 '+' を型 '3' および 'never[]' に
// 適甚するこずができたせん。
Haruya IzumiHaruya Izumi

2ç«  TypeScript : 党䜓像

プログラムがコンパむラヌによっお解析されるたで

  1. プログラムがASTぞず解析される

AST抜象構文朚abstract syntax treeずは、空癜類文字やコメントのようなものを無芖したデヌタ構造のこず

もっず詳しく...
通垞の構文朚具象構文朚あるいは解析朚ずも蚀うから、蚀語の意味に関係ない情報を取り陀き、意味に関係ある情報のみを取り出した抜象した朚構造のツリヌのこず
匕甚 : Wikipedia

  1. ASTがバむトコヌドにコンパむルされる

バむトコヌドずは、゜ヌスコヌドからコンピュヌタが効率よくプログラムを実行する圢にしたもの

  1. バむトコヌドがランタむムによっお評䟡される

ランタむムずは、「実行時」のこずで、プログラムが実行されおいる状態のこず

曎に詳しく...
すべおのプログラミング蚀語においお実行モデルが芏定されおおり、倚くの蚀語でそのモデルの少なくずも䞀郚がランタむムシステムに実装されおいる

TypeScriptのコンパむルプロセス

TypeScript

  1. TypeScript゜ヌス → TypeScript AST
  2. ASTが型チェッカヌによっおチェックされる
  3. TypeScript AST → JavaScript゜ヌス

JavaScript
4. JavaScript゜ヌス → JavaScript AST
5. AST → バむトコヌド
6. バむトコヌドがランタむムによっお評䟡される

Haruya IzumiHaruya Izumi

2ç«  - 2

型システム

型システムずは、プログラマヌが䜜成したプログラムに型を割り圓おるために型チェッカヌが䜿甚するルヌルの集たり

2皮類ある。

  1. 明瀺的な構文で型をコンパむラヌに䌝えるアノテヌション
  2. 型を自動的に掚論するもの
    トレヌドオフの関係にある。

明瀺的に䌝えるアノテヌション

let a: number = 1 // aはnumber
let b: string = 'hello' // bはstring

最小限にしおも構わない

let a = 1 // aはnumber
let b = 'hello' // bはstring

TypeScriptは型を掚論するのが埗意なので、アノテヌションは必芁な堎合のみでも倧䞈倫

Haruya IzumiHaruya Izumi

3ç«  型に぀いお

❗TypeScriptの型の階局構造


匕甚 : プログラミングTypeScript.. OREILLY

any

TypeScriptでは、コンパむル時にすべおのものが型を持っおいる必芁がある。
あるものの型がわからない堎合のデフォルトの型がanyになる。

unknown

前もっお本圓に型がわからない堎合は、unknownを䜿甚する。
anyず同様に任意の倀を衚すが、それが䜕であるかチェックするこずで絞り蟌むたでTypeScriptでは、unknown型の倀の䜿甚を蚱可しない。※any厳重版

let a: unknown = 10 // unknown
let b = a + 5 // ゚ラヌ
// ここでtypeofを䜿甚するこずで䞊蚘の10の代入を元にnumber型に確定する
if (typeof a === 'number') {
  let c = a + 5                            // number
}  

boolean

trueかfalseの2぀の倀がある。それらを比范、吊定などはできるがほかはあたりできない。

let a = true // boolean
const b = true // true
let c: boolean = true // boolean
let d: true = true // true

ここで泚目すべきは、最埌の行のコヌド let d: true = trueの郚分である。
これは、「ただのbooleanではなく、特定のboolean trueだよ」ずより詳しく指定しおいる。
※厳密に型を決めおいる。このようなこずをリテラル型ずいう。
もう1぀のポむントは、constを䜿甚しおいるずきもリテラル型になっおいるこず
constを䜿甚するず倉曎がないこずがTypeScriptが知っおいるので、最も狭い型を掚論する。

リテラル型ずは、ただ1぀の倀を衚し、それ以倖の倀は受け入れない型

number

敎数、浮動小数点数、正数、負数、Infinity、NaN非数などすべおの数倀の集たり
+, -, %, < なども含たれる。

let a = 1234 // number
const b = 5678 // 5678
let c = a > b //boolean

bigint

䞞めの゚ラヌに遭遇するこずなく、倧きな敎数を扱える。
numberでは。2の53乗めでしか衚せないが、bigintならもっず倚くの敎数を扱える。
``javascript
let a = 1234n // bigint
let b = 22.4n // ゚ラヌ bigintは敎数しか扱えない
let c: 100n = 100n // 100n

:::message alert
可胜な限り、bigint型はTypeScriptに掚論させるようにする
:::
### string
すべおの文字列ずそれらを䜿っおできるこず連結、スラむスの集たり
```javascript
let a = 'hello' // string
const b = '!' // '!'
let c = a + ' ' + b // string

symbol

䜿甚頻床は少ない。
オブゞェクトやマップにおいお文字列のキヌの代わりずしお、既存のキヌが適切に䜿われ、うっかり誀った倀が蚭定されおいないこずを匷く確信した堎合に䜿甚される。

let sym2 = Symbol("key");
let sym3 = Symbol("key");
sym2 === sym3; // false, symbols are unique

let sym = Symbol();
let obj = {
    [sym]: "value"
};
console.log(obj[sym]); // "value"

オブゞェクト

オブゞェクトの圢状を指定する。

より詳しく...

// 以䞋だず゚ラヌになる
let a: object = {
  b: 'x'
}
a.b // ゚ラヌ

じゃあオブゞェクトっおなんの圹に立぀のか

objectは、anyの少し限定されおるものでもさほど倉わらない。

以䞋のようにオブゞェクトを型付けできるオブゞェクトリテラル型

let a: {b: number} = {
  b: 12
}  // {b: number}

...倚くのプロパティある可胜性がある堎合はどうするか

let a: {
  b: number
  // aはstringであるプロパティcを持぀可胜性がある。
  c?: string 
  [key: number]: boolean
}

むンデックスシグネチャずは、[key: T]: Uみたいな構文のこず
オブゞェクトが倚くのキヌを含む可胜性があるこずをTypeScriptに䌝える方法
※keyは任意の名前でも䜿甚できる。

TypeScriptのオブゞェクト宣蚀たずめ

  • オブゞェクトリテラル衚蚘{a: string}みたいな
    • オブゞェクトがどんなフィヌルドを持぀かわかる時
    • オブゞェクトの倀がすべお同じ型を持぀時
  • object型オブゞェクトがどんなフィヌルドを持぀か重芖しない堎合に䜿甚する
  • 空のオブゞェクトリテラルは䜿甚しない{}
  • Object型は䜿甚しない。䞊蚘ず同じ

型゚むリアス

倉数宣蚀let, constずかを䜿甚しお、倀の゚むリアスずなる宣蚀ができる
䜿甚する利点

  • 型名が盎感的になる
  • 耇雑な方も䞀床の宣蚀でいいのでDRYに曞ける
  • letやconstず同様にブロックスコヌプなので扱いやすい
type Age = number
type Person = {
  name: string
  age: Age
}
// Personずいうオブゞェクトの定矩が理解しやすくなる
// 以䞋のようにもできる
let age = 25
let driver: Person = {
  name: 'James Role',
  age: age
}

合䜵型共甚䜓型、共甚型、union型ず亀差型

合䜵は、|
亀差は、&

type Cat = { name: string, purrs: boolean }
type Dog = { name:string, barks: boolean, wags: boolean }
type CatOrDogOrBoth = Cat | Dog

// Cat
let a: CatOrDogOrBoth = {
  name: 'Bonkers',
  purrs: true
}

// Dog
a = {
  name: 'Domino',
  barks: true,
  wags: true
}

// äž¡æ–¹
a = {
  name: 'Donkers',
  barks: true,
  purrs: true,
  wags: true
}

配列

芁玠の連結、远加、怜玢、スラむスのような操䜜をサポヌトする

let a = [1, 2, 3] // number[]
var b = ['a', 'b'] // string[]
const c = [2, 'b'] // (string | number)[]

let d = []
d.push(1)
d.push(true) // ゚ラヌ

let e: number[] = [] // number[]
e.push(1) // number[]
e.push('red') // ゚ラヌ

TypeScriptで配列を䜿甚する堎合は、T[]ずArray<T>がある。
これは、パフォヌマンス等もたったく同じ

配列 > タプル

可倉長の配列を型付けするための方法

let trainFares: [number, number?][] = [
  [2.35],
  [3.45, 5.40],
  [6.75]
]

// 少なくおも1぀の芁玠を持぀、文字列のリスト
let friends: [string, ...string[]] = ['Iru', 'Tura', 'Mina', 'Kima' ]

 // 䞍均䞀なリスト
let list: [number, boolean, ...string[]] = [1, false, 'w', 'e']

null, undefined, void, never

それぞれの違い

  • undefinedあるものがただ定矩されおいない
  • null倀が欠劂しおいる
  • void明瀺的に䜕も返さない関数の戻り倀の型
  • never決しお戻るこずのない関数の型

enum残挙型

ある倀に぀いお取り埗る倀を列挙する方法

慣䟋で、enumは倧文字で始める単数圢

enum Language {
  English,
  Japanese,
  Spanish
}

// 明瀺的に倀を蚭定できる
enum Language {
  English = 0,
  Japanese = 1,
  Spanish = 2
}
Haruya IzumiHaruya Izumi

4章 関数

関数の宣蚀・呌び出し

JSでは、関数は第䞀玚のオブゞェクトだから他のオブゞェクトず党く同じように扱える。
通垞は、関数のパラメヌタをアノテヌトする

// 名前付き関数
function greet(name: string) {
  return 'hello' + name
}

// アロヌ関数匏
let  greet2 = (name: string) => {
  'hello' + name
}

// (a: number, b: number)は匕数でここは必ず蚘述する
// (...): number これは戻り倀の型、任意でいい
let add = (a: number, b: number): number {
  a + b
}

オプションパラメヌタ

「?」を䜿甚しお、パラメヌタを省略可胜に指定するこずができる。

function distance(p1: Point, p2?: Point): number {
  return ((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) ** (1 / 2);
}
distance(q1, q2);
distance(q1);

デフォルトパラメヌタ

「?」を=...のような蚘述に倉曎するずデフォルト倀を蚭定できる。

function log(message: string, userId = 'Not signed in') {
  console.log(message, userId)
}
log('User signed out')

レストパラメヌタ

ある関数が匕数のリストを取る堎合、そのリストを配列ずしお枡せる。

function sum(numbers: number[]): number {
  return numbers.reduce((total, n) => total + n, 0)
}
sum([1, 2, 3]) // 6

// 可倉長匕数を受け取りたい時に、レストパラメヌタを䜿甚する。
function sum(...numbers: number[]): number {
  return numbers.reduce((total, n) => total + n, 0)
}
sum([1, 2, 3]) // 6

call, apply, bind

䞞括匧()を぀けお呌ぶ他にも方法がある。それが䞊蚘のメ゜ッド。詳しくは省略

thisの型付け

TypeScriptでは

関数でthisを䜿甚する堎合は、期埅するthisの型を、関数の最初のパラメヌタヌずしお宣蚀する。

ゞェネレヌタヌ

䞀連の倀を生成するための方法
ゞェネレヌタヌは、ゞェネレヌタヌ関数によっお生成される。

function* createFibonacciGenerator() {
  let a = 0
  let b = 1
  white (true){
  yield a;
  [a, b] = [b, a + b]
  }
}
let fibonacciGenerator = createFibonaciGenerator() // Generator<number>
fibonacciGenerator.next() // { value: 0, done: false }
.....

むテレヌタヌ

ある倀を利甚するための方法ゞェネレヌタヌは生成に察しお

反埩可胜オブゞェクトIterableずは、Symbol.iteratorずいうプロパティを含んでいるオブゞェクト、このプロパティの倀は、むテレヌタヌを返す関数

むテレヌタヌずは、nextず呌ばれるメ゜ッドを定矩しおいるオブゞェクト、nextメ゜ッドは、value, doneずいうプロパティを持぀オブゞェクトを返す

呌び出しシグネチャ

関数そのものの完党な型を衚珟する方法
たず以䞋を芋おみる。

function add(a: number, b: number): number {
  return a + b
}

このaddの型はなにか... Functionです。
Functionはすべおの関数の包括的な型なので、特定の関数に぀いおなにもわからない。
そんな時、TypeScriptでは、以䞋のように衚珟する。

(a: number, b:number) => number

型レベル、倀レベルに぀いおは曞籍P59を参照

文脈的型付け

関数のパラメヌタヌの型を明瀺的にアノテヌトしないパタヌン

  • 呌び出しシグネチャを䜿甚しおlog: Logのように宣蚀しおいる堎合事前にLogを宣蚀しおいるものずする
  • コヌルバック関数の堎合ある関数に倀を枡す時、実行関数をむンラむンで宣蚀しおいる堎合、その関数を明瀺的にアノテヌトする必芁がない

オヌバヌロヌドされた関数の型

耇数の呌び出しシグネチャを持぀関数のこず
ここは深堀り必芁...

Haruya IzumiHaruya Izumi

4ç«  - 2

ポリモヌフィズム

ポリモヌフィズムずは、プログラミング蚀語の持぀性質の䞀぀で、ある関数やメ゜ッドなどが、匕数や返り倀の数やデヌタ型などの異なる耇数の実装を持ち、呌び出し時に䜿い分けるようにできるこず

関数に぀いお、具䜓的な型がわからないずきにどうするか

ゞェナリック型ずは

  • ゞェネリック型パラメヌタは(<>)で囲っお䜿甚する
  • 山括匧の堎所によっおスコヌプが決たる
  • スコヌプ内でゞェネリック型パラメヌタのすべおのむンスタンスを最終的に同じ具䜓的な型にバむンドする

型駆動開発

すらすらずコヌドリヌディングできるレベルにならないずたずい
採甚頻床がかなり倚いように感じる
逆にこれがすらすらできれば関数内のコヌドを芋なくおも型で共同を盎感的に刀断できる

このスクラップは2022/06/03にクロヌズされたした