🐷

【TypeScript勉強記】:(自分用)型定義チートシート

2023/02/17に公開

学習素材

【日本一わかりやすいTypeScript入門】基本の型定義とアノテーション
【日本一わかりやすいTypeScript入門】関数のパラメーターと戻り値に型をつける
【日本一わかりやすいTypeScript入門】型エイリアス(type)でオブジェクトの型定義
【日本一わかりやすいTypeScript入門】積極的に使いたい配列・タプルの型定義
【日本一わかりやすいTypeScript入門】ジェネリック型を使いながらポリモーフィズムを理解する

基本的な型定義

プリミティブ型

内容
string 全ての文字列
number 整数、浮動小数点、正数、負数、無限大、NaN(非数)など全ての数値
boolean trueとfalse

存在しないことを表現する型

内容
null 値が欠如している状態
undefined 初期化されていない、かつ値が割り振られていない状態

*できる限りundefinedを使う

避ける型

内容
any どんな型でも許容する、安全でない型
unknown どんな型か不明。代入する値によって型が変わる

*APIで返ってくる値の型がわからない時などに、if文と合わせて使う場合がある

関数の型定義

関数で使われる型

内容
void return文を持たない関数の戻り値(alertを出すだけの関数、など)
never 決して戻ることのない関数の戻り値

関数の型定義の仕方

  1. パラメーター:関数宣言時に呼び出される値
  2. 引数:関数を呼び出す時に渡す値
  3. 戻り値:関数が返す値

オプションとデフォルト

順序 内容
オプションパラメーター パラメーターの最後に記述 オプショナル(?)をつける
デフォルトパラメーター 関係なく記述可能 イコール(=)で指定

可変長変数に型をつける

可変長変数は、関数呼び出し時に、引数を幾つでも渡せる。
しかし、安全ではないので、レストパラメーターを使う。

順序 内容
レストパラメーター パラメーターの最後に一つだけ指定可能 ...を指定

呼び出しシグネチャ

どのような関数なのかを定義する型定義。
記法はオブジェクトに、省略記法はアロー関数と似た記法

オブジェクトの型定義

オブジェクトの型定義

「構造的部分型」
= あるオブジェクトの構造だけを定義し、オブジェクトの名前は気にしない

object型はobjectであることを伝えるだけで、使用しない

const a: object = {
    name: 'Taro',
    age: 20
 }
a.name // Property 'name' does not exist on type 'object'.

オブジェクトリテラル

  • 構造を定義
  • 各プロパティに型を指定
let country: {
  language: string,
  name: string
} = {
  language: 'Japanese',
  name: 'Taro'
}

特別なプロパティ

  • オプショナル(?)のついたプロパティ:なくてもOK
  • readonlyのついたプロパティ:上書きできない
const fogefoge: {
    age: number,
    lastName: string,
    readonly firstName: string,
    gender?: string
  } = {
    age: 20,
    lastName: 'Yamada',
    firstName: 'Taro'
 }
 
 fogefoge.gender = 'male'
 fogefoge.lastName = 'Kamado'
 fogefoge.firstName = 'Taro' // Cannot assign to 'firstName' because it is a read-only property.

インデックスシグネチャ

オブジェクトが複数のプロパティを持つ可能性を示す

  • keyの型はstringかnumberのみ
const capitals: {
   [sountryName: string]: string
 } = {
   Japan: 'Tokyo',
   Korea: 'Seoul'
 }
 capitals.China = 'Beijing'
 capitals.Canada = 'Ottawa'

型エイリアスで型定義を再利用

型エイリアスとは

  • typeを使って、型に名前をつけて宣言できる
  • 同じ型を何度も定義する必要がなく、再利用できる
  • 型に名前をつけて、変数の役割を明確にする
type Country = {
  capital: string,
  language: string,
  name: string
}
const japan: Country = {
  capital: 'Tokyo',
  language: 'Japanese',
  name: 'Japan'
}
// 再利用
const usa: Country = {
  capital: 'Washington, D.C.',
  language: 'English',
  name: 'United States of America'
}

合併型(Union Types)と交差型(Intersection Types)

順序
合併型(Union Types) 型Aか型Bどちらかの型を持つ
交差型(Intersection Types) 型Aと型B両方の型を持つ(A, Bに共通する型ではない)
type Knight = {
  hp: number,
  sp: number,
  weapon: string,
  swordSkill: string
}

type Wizard = {
  hp: number,
  mp: number,
  weapon: string,
  magicSkill: string
}

// 合併型
type Adventure = Knight | Wizard

// 交差型
type Paladin = Knight & Wizard

// Knight寄りの冒険者
const adventure1: Adventure = {
  hp: 100,
  sp: 30,
  weapon: '木の剣',
  swordSkill: '三連斬り'
}

// Wizard寄りの冒険者
const adventure2: Adventure = {
  hp: 100,
  mp: 30,
  weapon: '木の杖',
  magicSkill: 'ファイヤボール'
}

const paladin: Paladin = {
  hp: 30,
  sp: 30,
  mp: 30,
  weapon: '木の剣',
  swordSkill: '三連斬り',
  magicSkill: 'ファイヤボール'
}

配列の型定義

配列の型定義は、2種類ある。

// 2種類のnumber型配列の定義
const odd: number[] = [1, 3, 5]
const even: Array<number> = [2, 4, 6]

シンプルな配列の型定義

// stringの配列
const colors: string[] = ['red', 'blue'] 
colors.push('yellow') // OK
colors.push(123) // NG

合併型の配列

const ids: (string | number)[] = ["ABC", 123]
ids.push("DEF")
ids.push(456)

配列の型推論

const generateSomeArray = () => {
  const someArray = [] //any[]
  someArray.push(123) // number[]
  someArray.push("ABC") // (string | number)[]
  return someArray
}

const someArray = generateSomeArray()
someArray.push(456)

厳格な配列:タプル

タプルは、配列の要素数と型を定義できる。
可変長(レストパラメーター)を使うこともできる。

// OK
let response: [number, string] = [200, "OK"]
// NG
response = [400, "Bad Request", "Email parameter is missing"] // Type '[number, string, string]' is not assignable to type '[number, string]'. Source has 3 element(s) but target allows only 2.
response = ["400", "Bad Request"] // Type 'string' is not assignable to type 'number'

// 可変長(レストパラメーター)を使ったタプル
// ...によって、1つ目の要素以降は、何個でも良い
const girlFriends: [string, ...string[]] = ["kana", "Miku", "Keiko"]
girlFriends.push("Misa")

ジェネリック型

ジェネリック型 = 「総称型(まとめて表すもの)」
ジェネリック型は、型を抽象化する。

以下のように、型の種類は異なるが、同じデータ構造を持っているので共通化したい場合、

const stringReduce = (array: string[], initialValue: string): string => {}
const numberReduce =(array: number[], initialValue: number): number => {}

ジェネチック型パラメーターで型をパラメーター化し、後から実パラメーターを渡す。
ジェネチック型パラメーターには、T, U, V, Wなどがよく使われる

type Reduce<T> = {
  (array: T[], initialValue: T): T
}

// 具体的な型をバインド
const reduce: Reduce<string> = (array, initialValue) => {}

ジェネリックの宣言方法

完全な呼び出しシグネチャ

  1. シグネチャ全体にジェネリック型を割り当てる
type GenericReduce<T> = {
  (array: T[], initialValue: T): T
}
  1. 個々のシグネチャにジェネリック型を割り当てる
type GenericReduce2 = {
  <T>(array: T[], initialValue: T): T
  <U>(array: U[], initialValue: U): U
}

省略記法

// 省略記法:シグネチャ全体にジェネリック型を割り当てる
type GenericReduce3<T> = (array: T[], initialValue: T) => T
// 省略記法:個々のシグネチャにジェネリック型を割り当てる
type GenericReduce4 = <T>(array: T[], initialValue: T) => T

型の種類は異なるが、構造が同じ

const stringReduce = (array: string[], initialValue: string): string => {
  let result = initialValue
  for (let i = 0; i < array.length; i++) {
    result += array[i];
  }
  return result
}
const numberReduce = (array: number[], initialValue: number): number => {
  let result = initialValue
  for (let i = 0; i < array.length; i++) {
    result += array[i];
  }
  return result
}

共通化後

// 共通化
type GenericReduce<T> = {
  (array: T[], initialValue: T): T
}

const genericStringReduce: GenericReduce<string> = (array, initialValue) => {
  let result = initialValue
  for (let i = 0; i < array.length; i++) {
    result += array[i];
  }
  return result
}

const genericNumberReduce: GenericReduce<number> = (array, initialValue) => { 
...(略)...
}

2つ以上のジェネチック型パラメーターを扱う

// 2つのジェネチック型パラメーターを使った、map関数のシグネチャ
// fn(itemという引数を持つコールバック関数)、返り値はUの配列
type Map<T, U> = (array: T[], fn: (item: T) => U) => U[]

// 文字列を渡して数値を返す関数
const mapStringsToNumbers: Map<string, number> = (array, fn) => {
  let result = []
  for (let i = 0; i < array.length; i++) {
    const item = array[i]
    result[i] = fn(item)
  }
  return result
}
const numbers = mapStringsToNumbers(["123", "456", "789"], (item) => Number(item))
// [123, 345, 678]

ポリモーフィズム

呼び出し側の共通化のことを言う。
polymorphism
= 多態性・多相性 = 色々な形に変化できること

TypeScriptにおける呼び出し側の共通化とは、

  • 型を抽象化する
  • 呼び出すときに具体的な型を渡す[1]

脚注
  1. 画像引用元 ↩︎

Discussion