TypeScriptのUnion型(合併型、共用体型)の概要と具体例

JavaScript

Union型(Union Types、合併型、共用体型)について

Union型(Union Types)は型 | 型のように|で型を連結し、『いずれかの型』を表現します。
Union型は日本語では合併型と呼ばれたり1 2、共用体型と呼ばれたりします3 4 5

補足: Union型は直和型と訳すのは適切ではない?

Union型を直和型と表現している記事もありますが6 7、TypeScriptのUnion型は直和型ではないという意見もあります。8

ですので、TypeScriptの文脈でUnion Typesを日本語訳する際は合併型もしくは共用体型としておくのが無難です。

なお、直和型や直積型という言葉はHaskellの文脈でよく利用されているようです。9 10

Union型の具体例

Union型の具体例を紹介します。

プリミティブ型のUnion型の利用例

Union型に含まれているプリミティブ型が利用できます。

type StringOrNumber = string | number;

// OK
const str: StringOrNumber = 'Hello'

// OKE
const num: StringOrNumber = 123

// NG
// Union型で定義されていないプリミティブ型を利用している
const bool: StringOrNumber = true
// Type 'boolean' is not assignable to type 'StringOrNumber'.ts(2322)

オブジェクト型のUnion型の利用例

Union型に含まれているオブジェクト型が利用できます。
Union型に含まれていないオブジェクト型を利用したり、オブジェクト型に余計なプロパティを含めたりするとエラーになります。

以下はSquare型とRectangle型とTriangle型で構成されたShapeというUnion型を利用する例です。

type Square = {
  side: number;
};

type Rectangle = {
  length: number;
  width: number;
};

type Triangle = {
  base: number;
  height: number;
};

type Shape = Square | Rectangle | Triangle;

// OK
const square: Shape = {
  side: 10,
};

// NG
// Union型に含まれていないオブジェクト型
const circle: Shape = {
  radius: 5,
};
// Type '{ radius: number; }' is not assignable to type 'Shape'.

// NG
// triangleにangle1, angle2, angle3という余計なプロパティを定義している
const triange: Shape = {
  base: 5,
  height: 10,
  angle1: 90,
  angle2: 60,
  angle3: 30,
};
// Type '{ base: number; height: number; angle1: number; angle2: number; angle3: number; }' is

参考: オブジェクト型に余計なプロパティを含めてもエラーにならないケース

さきほど、オブジェクト型に余計なプロパティを含めるとエラーになると説明しましたが例外があります。
それはUnion型に含まれる別のオブジェクト型のプロパティの場合です。

以下は余計なプロパティを含めてもエラーにならない具体例です。検証環境はTypeScript 4.4.3です。

type Square = {
  side: number;
};

type Rectangle = {
  length: number;
  width: number;
};

type Triangle = {
  base: number;
  height: number;
};

type Shape = Square | Rectangle | Triangle;

// OK
// Rectangle型として扱うにはheightが余計なプロパティであるが、Union型に含まれているTriangle型で定義されているプロパティなのでエラーにならない
const cube: Shape = {
  length: 10,
  width: 10,
  height: 5,
};

cubeオブジェクトはRectangle型とみなすとheightが余計なプロパティです。
しかし、heightはUnion型に含まれるTriangle型のプロパティであるためエラーになりません。

TypeScriptのunion型はorです 〜union型、構造的部分型、余剰プロパティチェックの話〜によると互換性の関係でこのような挙動になっているとのことです。

リテラル型のUnion型の利用例

Union型に含まれているリテラル型が利用できます。
Union型で文字列リテラルを利用する例は以下の通りです。

type Color = "red" | "green" | "blue";

// OK
const redColor: Color = "red";

// NG
const yellowColor: Color = "yellow";
// Type '"yellow"' is not assignable to type 'Color'.ts(2322)

なお、リテラル型のUnion型を利用するとEnum型(列挙型)をUnion型で書き換えられます。
Enum型とUnion型の比較は【TypeScript】Enum型からUnion型に書き換える方法と具体例で紹介しています。

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考