聯(lián)合類型(Union Types)
輸入的值可能是多種類型中的一種。
有時(shí)創(chuàng)建一組類型并以其中一個(gè)類型為準(zhǔn)是很有用的豹芯。 例如琅捏,你可能希望編寫一個(gè)接受一組原始值類型的函數(shù)聊品。
// @flow
function toStringPrimitives(value: number | boolean | string) {
return String(value);
}
toStringPrimitives(1); // Works!
toStringPrimitives(true); // Works!
toStringPrimitives('three'); // Works!
// $ExpectError
toStringPrimitives({ prop: 'val' }); // Error!
// $ExpectError
toStringPrimitives([1, 2, 3, 4, 5]); // Error!
聯(lián)合類型語(yǔ)法
聯(lián)合類型是通過豎線|
連接的任意數(shù)量的類型。
Type1 | Type2 | ... | TypeN
或者
type Foo =
| Type1
| Type2
| ...
| TypeN
聯(lián)合類型的每個(gè)成員可以是任何類型则涯,甚至是另一個(gè)聯(lián)合類型复局。
type Numbers = 1 | 2;
type Colors = 'red' | 'blue'
type Fish = Numbers | Colors;
傳入與處理
當(dāng)調(diào)用接受聯(lián)合類型的函數(shù)時(shí),我們必須傳入其中的一種類型粟判。但是在我們的函數(shù)里面,我們需要處理所有可能的類型峦剔。
// @flow
// $ExpectError
function toStringPrimitives(value: number | boolean | string): string { // Error!
if (typeof value === 'number') {
return String(value);
} else if (typeof value === 'boolean') {
return String(value);
}
}
這里我們沒有處理每一種情況(漏掉了string
類型的處理)档礁,F(xiàn)low拋出異常。
聯(lián)合與改進(jìn)
當(dāng)你有一個(gè)聯(lián)合類型的值時(shí)吝沫,把它分開并分別處理每個(gè)類型通常是有用的呻澜。使用Flow中的聯(lián)合類型递礼,可以將值精簡(jiǎn)為單個(gè)類型。上面的例子中我們可以使用JavaScript的typeof
運(yùn)算符分別處理數(shù)字大小寫羹幸。
// @flow
function toStringPrimitives(value: number | boolean | string) {
if (typeof value === 'number') {
return value.toLocaleString([], { maximumSignificantDigits: 3 }); // Works!
}
// ...
}
不相交聯(lián)合
例如脊髓,假設(shè)在發(fā)送請(qǐng)求后,我們有一個(gè)處理服務(wù)器響應(yīng)的函數(shù)栅受。當(dāng)請(qǐng)求成功時(shí)将硝,我們將返回一個(gè)成功的屬性。
{ success: true, value: false };
當(dāng)請(qǐng)求失敗時(shí)屏镊,我們將返回一個(gè)失敗的屬性依疼。
{ success: false, error: 'Bad request' };
我們可以嘗試在單個(gè)對(duì)象類型中表示這兩個(gè)對(duì)象。
// @flow
type Response = {
success: boolean,
value?: boolean,
error?: string
};
function handleResponse(response: Response) {
if (response.success) {
// $ExpectError
var value: boolean = response.value; // Error!
} else {
// $ExpectError
var error: string = response.error; // Error!
}
}
試圖將這兩種不同的類型合并成一個(gè)單一的類型并使用時(shí)而芥,F(xiàn)low會(huì)拋出異常律罢。相反,如果我們創(chuàng)建了兩種對(duì)象類型的聯(lián)合類型棍丐,F(xiàn)low將能夠根據(jù)success屬性知道我們正在使用哪個(gè)對(duì)象误辑。
// @flow
type Success = { success: true, value: boolean };
type Failed = { success: false, error: string };
type Response = Success | Failed;
function handleResponse(response: Response) {
if (response.success) {
var value: boolean = response.value; // Works!
} else {
var error: string = response.error; // Works!
}
}
確切類型的不相交聯(lián)合
不相交聯(lián)合要求你通過單個(gè)屬性區(qū)分不同對(duì)象。
// @flow
type Success = { success: true, value: boolean };
type Failed = { error: true, message: string };
function handleResponse(response: Success | Failed) {
if (response.success) {
// $ExpectError
var value: boolean = response.value; // Error!
}
}
這由于寬度子類型的緣故歌逢,F(xiàn)low允許傳遞一個(gè)比預(yù)期的擁有更多屬性的對(duì)象稀余。
// @flow
type Success = { success: true, value: boolean };
type Failed = { error: true, message: string };
function handleResponse(response: Success | Failed) {
// ...
}
handleResponse({
success: true,
error: true,
value: true,
message: 'hi'
});
除非對(duì)象彼此間差異,否則無(wú)法區(qū)分趋翻。所以睛琳,只有使用確切的對(duì)象類型才能解決問題。
// @flow
type Success = {| success: true, value: boolean |};
type Failed = {| error: true, message: string |};
type Response = Success | Failed;
function handleResponse(response: Response) {
if (response.success) {
var value: boolean = response.value;
} else {
var message: string = response.message;
}
}
有了確切的對(duì)象類型踏烙,我們不能添加額外的屬性师骗,所以對(duì)象彼此間差異,我們能夠區(qū)分哪個(gè)是哪個(gè)讨惩。