T
かU
どちらでも扱えるときに間に|
を挟んでT | U
という感じで記述します。飲む
関数の場合Water | Curry
どちらも成り立つというような感じです。
Union の例
以下はNumber
でキャストするのでstring
とnumber
どちらでも大丈夫です。
const onePlus = (num: string | number) => Number(num) + 1;
console.log(onePlus('1')); // 2
次もそれぞれに存在するプロパティを使うので大丈夫な関数です。
interface Value {
value: number;
}
interface Foo extends Value {
foo: any;
}
interface Bar extends Value {
bar: any;
}
const onePlus = (value: Foo | Bar) => value.value + 1;
JavaScript 構文で絞り込み
次のコードはstring | string[]
を受け取って必ずstring[]
で返したい関数です。つまりstring
だった時は配列に変換してあげる必要があります。
こういう時に使うのがtypeof
やArray.isArray
です。TypeScriptは賢いのでこの辺りを使うと型を絞り込んでくれます。
const ensureArray = (value: string | string[]) => {
if (typeof value === 'string') {
// ここで`value`は`string`型
value = [value];
}
// または `!Array.isArray(value)`を使う
return value;
}
他に型の絞り込みに使えるもので
instanceof
in
例えば
'foo' in value
でFoo
に絞込
があります。
複雑な絞り込みは Type Guards を使う
複雑な絞り込みの時はType Guards
を使うとスッキリします。これにはarg is T
という奇妙な戻り値を返すようにします。
例えば以下のisFoo
は値のtype: 'foo'
でhoge
プロパティを持ってたらFoo
ということにしてる関数です。
interface Foo {
type: 'foo';
hoge: string;
}
interface Bar {
type: 'bar';
fuga: string;
}
function isFoo(arg: Foo | Bar): arg is Foo {
return (
arg.type === 'foo' && Object.prototype.hasOwnProperty.call(arg, 'hoge')
);
}
// モック
const arg: Foo | Bar = undefined as any;
if (isFoo(arg)) {
// ここで`arg`は`Foo`型
console.log(arg.hoge);
}