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;
}他に型の絞り込みに使えるもので
instanceofin例えば
'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);
}