Open1

[読書メモ]プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで(ISBN: 978-4-297-12747-3)

くそぼうずくそぼうず

6章 高度な型

  • ユーザ定義型ガードを使えば、引数に与えられた値が特定の型であることを示すことができる。
// 引数名 is 型という書き方をする。返り値はbooleanになる。
function isStringOrNumber(value: unknown): value is string | number {
  return typeof value === 'string' || typeof value === 'number';
}

const something: unknown = 123;

if (isisStringOrNumber(something)) {
  // NOTE: somethingがstring型あるいはnumber型として扱うことができる
  console.log(something.toString());
}
function isStringOrNumber(value: unknown): boolean {
  return typeof value === 'string' || typeof value === 'number';
}

const something: unknown = 123;

if (isisStringOrNumber(something)) {
  // NOTE: コンパイルエラーが出る
  console.log(something.toString());
}
  • ただし、ユーザ定義型ガードは自分で書く必要があり、実装にミスがあると型安全性を破壊し得る危険性があるので注意

6.8 力試し

type Some<T> = {
  tag: 'some',
  value: T
};

type None = {
  tag: "none"
};

type Option<T> = Some<T> | None;

const showNumber = (value: Option<number>): void => {
  if (value.tag === 'some') {
    console.log(value.value);
  } else {
    console.log('nothing');
  }
};

// ユーザ定義型ガードを使ってtagがsomeかどうか判定する
function isSome<T>(obj: Option<T>): obj is { tag: 'some', value: T } {
  if (obj == null) return false;
  return (obj.tag === 'some');
}

// objのtagがsomeの時は値を出力する
function showNumberIfExists(obj: Option<number>) {
  if (isSome(obj)) {
    console.log(obj.value);
  }
}

function mapOption<T, U>(obj: Option<T>, callback: (value: T) => U): Option<U> {
  switch (obj.tag) {
    case "some":
      return { tag: "some", value: callback(obj.value) };
    case "none": 
      return { tag: "none" };
  }
}
  • キーワード
    • ユニオン型・インターセクション型・リテラル型・型の絞り込み(typeof)・keyof型(keyof T)・lookup型(T[K])・ユーザ定義型ガード・mapped types({[P in K]: T} Pか型変数)・condtitional types(X extends Y ? S :T)・組み込み型