TypeScript 型 メモ


型リテラル

[]

  • 空のTupleを表す
  • Params<T>は関数の引数がないときに引数の型は[]になる

any

  • すべての型の値を代入することができる
  • あらゆるプロパティがあるものとしてアクセスすることができる
  • すなわち型システムとしてこいつは崩壊しているので使用するべきではない
const notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn’t check)

unknown

  • 他の言語で言うany

TypeScript 3.0のunknown型 - タイプセーフなany - Qiita

void

  • 他の言語で言う普通のvoid、関数が何も返さないときの値
  • 一応nullundefinedスーパータイプになれる
let unusable: void = undefined;
unusable = null; // OK if `—strictNullChecks` is not given

never

  • bottom型と呼ばれる値を持たない型
  • 決して処理が終わらないものを表すときに使用する i.e. while(truc)、例外のthrow
  • 集合論における空集合のようなものなので、あらゆる型に代入できるがnever以外を代入できない
const a: never = 1 // compile error
const b: number = never // ok

never型とのunion type

  • neverと他の型のunion typeはneverが消える
number | never == number

型コンストラクタ

Required<T>

  • Tの内nullableな属性の方を全てマストにする

Parameters<T>

  • Tが関数ならばその引数の型を返す
  • そうでないならneverを返す

Exclude<T, U>

  • TがUのサブタイプならneverを返し、そうでないならTを返す
  • union distributionと組み合わせることでunionから不要な物を削除できる
type A = "a" | "b"
type B = "b"

Exclude<A, B>
// => "a"

Pick<T, K extends keyof T>

  • Tからunion typeであるKに含まれるkeyの値だけを取り出す
type A = {a: any, b: any}
Pick<A, "a">
// => {a: any}

Omit<T, K extends keyof any>

  • TからKをのぞいた型を返す

型演算子

keyof T

  • Tのプロパティのキーからなるunion typeを返す
type T = {a: any; b: any}
keyof T
// => "a" | "b"

in

  • mapped typeと呼ばれる機能を実現するためのもの
  • 配列の型の一つ一つを処理して新たな型を返すようなときに使用する
type Readonly<T> = {
    readonly [P in keyof T]: T[P]; // Tのキー全てにreadonly属性をつけた新たな型を定義している
};

TypeScript2.1.4 で導入された keyof キーワードと in キーワード、そして Lookup Types と Mapped Types - 角待ちは対空

extends

型の境界

  • ある型が他の型のサブタイプであることを指定する場合に使用する
const apply<T extends (...args: any[]) => any, A extends any[]>(f: T, args: A) => f(...args)

apply((...args: number[]) => args.length, [1, 2])
// => 2

conditional type

  • ある型が別の型のサブタイプかどうかで型を分岐させる
declare function f<T extends boolean>(x: T): T extends true ? string : number;

// Type is 'string | number'
let x = f(Math.random() < 0.5);

TypeScript: Handbook - Advanced Types

  • 更にinferを使用することで型変数を定義し、それを用いて返す型を定義することができる
// Rを型変数として定義し、条件にあうときはそのRを用いて型を返す
// inferがなければRはそもそも定義されていない型変数なので使用できない
type ReturnType<T> = T extends (args: any[]) => infer R ? R : any;

union typeのサブタイプとextend判定

  • union typeのサブタイプはその候補を減らした型が当てはまる
type T = "a" | "b"
a extends T // => true
b extends T // => false
  • union typeの候補数を増やしても同様

union distribution

  • 上記のunion typeにおけるサブタイプとスーパータイプの関係性を保証するのがunion distributionという仕組み
  • 簡単に言うとunion typeの対するextends判定は分配法則に従って実行される
type A = number[] | string
type ArrayValue<T> = T extends (infer U)[] ? U : undefined
ArrayValue<A> // => number | undefined

ユースケース

スマートキャストするための型判定関数の作成

isを使用する

const isString = (arg: any): arg is string  => typeof arg === "string";

const foo = 'foo' as any // ここではanyとして振る舞いたい

if (isString(foo)) {
  // isStringの結果、arg is string = foo is string = fooはstring型であることが確定している
    foo.length // fooをas anyしたけどfooはstringとして解釈される
}

Advanced Types · TypeScript

nullableをnon nullにキャストする

!(Non-null assertion operator)を使用する

const a: string? = ""
const b: string = a // compile error
const c: string = a! // success