flow中文文檔(七)


接口類型

Flow中的類名義上是鍵入的懂讯。這意味著當(dāng)你有兩個(gè)單獨(dú)的類時(shí)圾叼,即使它們具有相同的屬性和方法相恃,也不能使用一個(gè)類代替另一個(gè)钝满。

// @flow
class Foo {
  serialize() { return '[Foo]'; }
}

class Bar {
  serialize() { return '[Bar]'; }
}

// $ExpectError
const foo: Foo = new Bar(); // Error!

相反,您可以使用接口來(lái)聲明您期望的類的結(jié)構(gòu)袖扛。

// @flow
interface Serializable {
  serialize(): string;
}

class Foo {
  serialize() { return '[Foo]'; }
}

class Bar {
  serialize() { return '[Bar]'; }
}

const foo: Serializable = new Foo(); // Works!
const bar: Serializable = new Bar(); // Works!

您還可以使用implements來(lái)告訴Flow您希望該類與接口匹配砸泛。這可以防止您在編輯類時(shí)進(jìn)行不兼容的更改。

// @flow
interface Serializable {
  serialize(): string;
}

class Foo implements Serializable {
  serialize() { return '[Foo]'; } // Works!
}

class Bar implements Serializable {
  // $ExpectError
  serialize() { return 42; } // Error!
}

您還可以使用具有多個(gè)接口的工具蛆封。

class Foo implements Bar, Baz {
  // ...
}

接口語(yǔ)法

接口是使用關(guān)鍵字interface唇礁,后跟其名稱和包含類型定義主體的塊創(chuàng)建的。

interface MyInterface {
  // ...
}

塊的語(yǔ)法與對(duì)象類型的語(yǔ)法匹配惨篱,并具有所有相同的功能


接口方法

您可以按照與對(duì)象方法相同的語(yǔ)法向接口添加方法盏筐。

interface MyInterface {
  method(value: string): number;
}

接口屬性

您可以按照與對(duì)象屬性相同的語(yǔ)法向接口添加屬性。

interface MyInterface {
  property: string;
}

接口屬性也是可選的砸讳。

interface MyInterface {
  property?: string;
}

接口Maps

您可以使用與對(duì)象相同的方式創(chuàng)建“索引器屬性”琢融。

interface MyInterface {
  [key: string]: number;
}

接口泛型

接口也可以有自己的泛型界牡。

interface MyInterface<A, B, C> {
  property: A;
  method(val: B): C;
}

接口泛型已參數(shù)化。使用接口時(shí)漾抬,需要為每個(gè)泛型傳遞參數(shù)宿亡。

// @flow
interface MyInterface<A, B, C> {
  foo: A;
  bar: B;
  baz: C;
}

var val: MyInterface<number, boolean, string> = {
  foo: 1,
  bar: true,
  baz: 'three',
};

接口屬性變量(只讀和只寫)

默認(rèn)情況下,接口屬性是不變的奋蔚。但是您可以添加修飾符以使它們協(xié)變(只讀)或逆變(只寫)她混。

interface MyInterface {
  +covariant: number;     // read-only
  -contravariant: number; // write-only
}

接口上的協(xié)變(只讀)屬性

您可以通過(guò)在屬性名稱前添加加號(hào)+來(lái)使屬性協(xié)變。

interface MyInterface {
  +readOnly: number | string;
}

這允許您傳遞更具體的類型來(lái)代替該屬性泊碑。

// @flow
// $ExpectError
interface Invariant {  property: number | string }
interface Covariant { +readOnly: number | string }

var value1: Invariant = { property: 42 }; // Error!
var value2: Covariant = { readOnly: 42 }; // Works!

由于協(xié)方差的工作原理坤按,協(xié)變屬性在使用時(shí)也變?yōu)橹蛔x。這對(duì)普通屬性有用馒过。

// @flow
interface Invariant {  property: number | string }
interface Covariant { +readOnly: number | string }

function method1(value: Invariant) {
  value.property;        // Works!
  value.property = 3.14; // Works!
}

function method2(value: Covariant) {
  value.readOnly;        // Works!
  // $ExpectError
  value.readOnly = 3.14; // Error!
}

接口上的逆變(只寫)屬性

您可以通過(guò)在屬性名稱前添加減號(hào)來(lái)創(chuàng)建屬性逆變臭脓。

interface InterfaceName {
  -writeOnly: number;
}

這允許您傳遞一個(gè)不太具體的類型來(lái)代替該屬性。

// @flow
interface Invariant     {  property: number }
interface Contravariant { -writeOnly: number }

var numberOrString = Math.random() > 0.5 ? 42 : 'forty-two';

// $ExpectError
var value1: Invariant     = { property: numberOrString };  // Error!
var value2: Contravariant = { writeOnly: numberOrString }; // Works!

由于逆變的工作原理腹忽,逆變屬性在使用時(shí)也會(huì)變?yōu)橹粚懤蠢邸_@對(duì)普通屬性有用。

interface Invariant     {   property: number }
interface Contravariant { -writeOnly: number }

function method1(value: Invariant) {
  value.property;        // Works!
  value.property = 3.14; // Works!
}

function method2(value: Contravariant) {
  // $ExpectError
  value.writeOnly;        // Error!
  value.writeOnly = 3.14; // Works!
}

泛型

泛型(有時(shí)稱為多態(tài)類型)是一種抽象類型的方法窘奏。 想象一下編寫以下身份函數(shù)嘹锁,它返回傳遞的任何值。

function identity(value) {
  return value;
}

我們?cè)趪L試為此函數(shù)編寫特定類型時(shí)會(huì)遇到很多麻煩着裹,因?yàn)樗赡苁侨魏螙|西领猾。

function identity(value: string): string {
  return value;
}

相反,我們可以在函數(shù)中創(chuàng)建泛型(或多態(tài)類型)骇扇,并使用它代替其他類型摔竿。

function identity<T>(value: T): T {
  return value;
}

泛型可以在函數(shù),函數(shù)類型少孝,類继低,類型別名和接口中使用。

警告:Flow不會(huì)推斷泛型類型稍走。如果您希望某些東西具有泛型類型袁翁,請(qǐng)對(duì)其進(jìn)行注釋。否則婿脸,F(xiàn)low可能會(huì)推斷出比您預(yù)期的多態(tài)性更低的類型粱胜。

在下面的示例中,我們忘記使用泛型類型正確地注釋 identity 盖淡,因此當(dāng)我們嘗試將其分配給func時(shí)會(huì)遇到麻煩年柠。另一方面凿歼,genericIdentity已正確輸入褪迟,我們可以按預(yù)期使用它冗恨。

// @flow

type IdentityWrapper = {
  func<T>(T): T
}

function identity(value) {
  return value;
}

function genericIdentity<T>(value: T): T {
  return value;
}

// $ExpectError
const bad: IdentityWrapper = { func: identity }; // Error!
const good: IdentityWrapper = { func: genericIdentity }; // Works!

具有泛型的函數(shù)

函數(shù)可以通過(guò)在函數(shù)參數(shù)列表之前添加類型參數(shù)列表<T>來(lái)創(chuàng)建泛型。 您可以在函數(shù)(參數(shù)或返回類型)中添加任何其他類型的相同位置使用泛型味赃。

function method<T>(param: T): T {
  // ...
}

function<T>(param: T): T {
  // ...
}

具有泛型的函數(shù)類型

函數(shù)類型可以通過(guò)在函數(shù)類型參數(shù)列表之前添加類型參數(shù)list <T>掀抹,以與普通函數(shù)相同的方式創(chuàng)建泛型心俗。 您可以在函數(shù)類型(參數(shù)或返回類型)中添加任何其他類型的相同位置使用泛型傲武。

<T>(param: T) => T

然后將其用作自己的類型。

function method(func: <T>(param: T) => T) {
  // ...
}

具有泛型的類

類可以通過(guò)將類型參數(shù)列表放在類的主體之前來(lái)創(chuàng)建泛型城榛。

class Item<T> {
  // ...
}

您可以在類中添加任何其他類型的相同位置使用泛型(屬性類型和方法參數(shù)/返回類型)揪利。

class Item<T> {
  prop: T;

  constructor(param: T) {
    this.prop = param;
  }

  method(): T {
    return this.prop;
  }
}

具有泛型的類型別名

type Item<T> = {
  foo: T,
  bar: T,
};

具有泛型的接口

interface Item<T> {
  foo: T,
  bar: T,
}

泛型特性

泛型就像變量一樣

泛型類型很像變量或函數(shù)參數(shù),除了它們用于類型狠持。只要它們?cè)诜秶鷥?nèi)疟位,您就可以使用它們。

function constant<T>(value: T) {
  return function(): T {
    return value;
  };
}

根據(jù)需要?jiǎng)?chuàng)建盡可能多的泛型

您可以在類型參數(shù)列表中根據(jù)需要使用這些泛型喘垂,并根據(jù)需要命名它們:

function identity<One, Two, Three>(one: One, two: Two, three: Three) {
  // ...
}

泛型跟蹤

當(dāng)對(duì)值使用泛型類型時(shí)甜刻,F(xiàn)low將跟蹤該值并確保您不會(huì)將其替換為其他值。

// @flow
function identity<T>(value: T): T {
  // $ExpectError
  return "foo"; // Error!
}

function identity<T>(value: T): T {
  // $ExpectError
  value = "foo"; // Error!
  // $ExpectError
  return value;  // Error!
}

Flow跟蹤您通過(guò)泛型的值的特定類型正勒,以便稍后使用得院。

// @flow
function identity<T>(value: T): T {
  return value;
}

let one: 1 = identity(1);
let two: 2 = identity(2);
// $ExpectError
let three: 3 = identity(42);

將類型添加到泛型

與 mixed 類似,泛型具有“未知”類型章贞。您不能使用泛型祥绞,就好像它是特定類型一樣。

// @flow
function logFoo<T>(obj: T): T {
  // $ExpectError
  console.log(obj.foo); // Error!
  return obj;
}

您可以優(yōu)化類型阱驾,但泛型仍然允許傳入任何類型就谜。

// @flow
function logFoo<T>(obj: T): T {
  if (obj && obj.foo) {
    console.log(obj.foo); // Works.
  }
  return obj;
}

logFoo({ foo: 'foo', bar: 'bar' });  // Works.
logFoo({ bar: 'bar' }); // Works. :(

相反,您可以像使用函數(shù)參數(shù)一樣為泛型添加類型里覆。

// @flow
function logFoo<T: { foo: string }>(obj: T): T {
  console.log(obj.foo); // Works!
  return obj;
}

logFoo({ foo: 'foo', bar: 'bar' });  // Works!
// $ExpectError
logFoo({ bar: 'bar' }); // Error!

這樣丧荐,您可以保留泛型的行為,同時(shí)僅允許使用某些類型喧枷。

// @flow
function identity<T: number>(value: T): T {
  return value;
}

let one: 1 = identity(1);
let two: 2 = identity(2);
// $ExpectError
let three: "three" = identity("three");

泛型充當(dāng)邊界

// @flow
function identity<T>(val: T): T {
  return val;
}

let foo: 'foo' = 'foo';           // Works!
let bar: 'bar' = identity('bar'); // Works!

在Flow中虹统,大多數(shù)情況下,當(dāng)您將一種類型傳遞到另一種類型時(shí)隧甚,您將失去原始類型车荔。因此,當(dāng)您將特定類型傳遞給不太具體的一個(gè)流程“界限”時(shí)戚扳,它曾經(jīng)是更具體的東西忧便。

// @flow
function identity(val: string): string {
  return val;
}

let foo: 'foo' = 'foo';           // Works!
// $ExpectError
let bar: 'bar' = identity('bar'); // Error!

泛型允許您在添加約束時(shí)保留更具體的類型。通過(guò)這種方式帽借,泛型上的類型充當(dāng)“邊界”珠增。

// @flow
function identity<T: string>(val: T): T {
  return val;
}

let foo: 'foo' = 'foo';           // Works!
let bar: 'bar' = identity('bar'); // Works!

請(qǐng)注意超歌,如果您具有綁定泛型類型的值,則不能將其用作更具體的類型蒂教。

// @flow
function identity<T: string>(val: T): T {
  let str: string = val; // Works!
  // $ExpectError
  let bar: 'bar'  = val; // Error!
  return val;
}

identity('bar');

參數(shù)化泛型

泛型有時(shí)允許您將類似參數(shù)的類型傳遞給函數(shù)巍举。這些被稱為參數(shù)化泛型(或參數(shù)多態(tài))。

例如凝垛,參數(shù)化具有泛型的類型別名懊悯。當(dāng)你去使用它時(shí),你必須提供一個(gè)類型參數(shù)梦皮。

type Item<T> = {
  prop: T,
}

let item: Item<string> = {
  prop: "value"
};

您可以將此視為將函數(shù)傳遞給函數(shù)炭分,只有返回值是您可以使用的類型。

類(當(dāng)用作類型時(shí))剑肯,類型別名和接口都要求您傳遞類型參數(shù)欠窒。函數(shù)和函數(shù)類型沒(méi)有參數(shù)化泛型。

classes

// @flow
class Item<T> {
  prop: T;
  constructor(param: T) {
    this.prop = param;
  }
}

let item1: Item<number> = new Item(42); // Works!
// $ExpectError
let item2: Item = new Item(42); // Error!

Type Aliases 類型別名

// @flow
type Item<T> = {
  prop: T,
};

let item1: Item<number> = { prop: 42 }; // Works!
// $ExpectError
let item2: Item = { prop: 42 }; // Error!

接口

// @flow
interface HasProp<T> {
  prop: T,
}

class Item {
  prop: string;
}

(Item.prototype: HasProp<string>); // Works!
// $ExpectError
(Item.prototype: HasProp); // Error!

添加參數(shù)化泛型的默認(rèn)值

您還可以像參數(shù)函數(shù)一樣為參數(shù)化泛型提供默認(rèn)值退子。

type Item<T: number = 1> = {
  prop: T,
};

let foo: Item<> = { prop: 1 };
let bar: Item<2> = { prop: 2 };

使用類型時(shí)岖妄,必須始終包括括號(hào)<>(就像函數(shù)調(diào)用的括號(hào)一樣)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寂祥,一起剝皮案震驚了整個(gè)濱河市荐虐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丸凭,老刑警劉巖福扬,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惜犀,居然都是意外死亡铛碑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門虽界,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)汽烦,“玉大人,你說(shuō)我怎么就攤上這事莉御∑餐蹋” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵礁叔,是天一觀的道長(zhǎng)牍颈。 經(jīng)常有香客問(wèn)我,道長(zhǎng)琅关,這世上最難降的妖魔是什么煮岁? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上画机,老公的妹妹穿的比我還像新娘勤篮。我一直安慰自己,他們只是感情好色罚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著账劲,像睡著了一般戳护。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瀑焦,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天腌且,我揣著相機(jī)與錄音,去河邊找鬼榛瓮。 笑死铺董,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的禀晓。 我是一名探鬼主播精续,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粹懒!你這毒婦竟也來(lái)了重付?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凫乖,失蹤者是張志新(化名)和其女友劉穎确垫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帽芽,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡删掀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了导街。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片披泪。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖搬瑰,靈堂內(nèi)的尸體忽然破棺而出付呕,到底是詐尸還是另有隱情,我是刑警寧澤跌捆,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布徽职,位于F島的核電站,受9級(jí)特大地震影響佩厚,放射性物質(zhì)發(fā)生泄漏姆钉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潮瓶。 院中可真熱鬧陶冷,春花似錦、人聲如沸毯辅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)思恐。三九已至沾谜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胀莹,已是汗流浹背基跑。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留描焰,地道東北人媳否。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像荆秦,于是被迫代替她去往敵國(guó)和親篱竭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理步绸,服務(wù)發(fā)現(xiàn)室抽,斷路器,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔靡努,今天18年5月份再次想寫文章坪圾,發(fā)現(xiàn)簡(jiǎn)書還為我保存起的...
    Jenaral閱讀 2,737評(píng)論 2 9
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981閱讀 15,890評(píng)論 2 11
  • 從小聽過(guò)了那么多大道理和經(jīng)驗(yàn)之談兽泄,卻依舊選了坑坑洼洼的路,走得曲曲折折漾月,把自己摔得鼻青臉腫病梢,許是再好的道理也要自己...
    輕塵印閱讀 348評(píng)論 0 0
  • 文|九月流云 參賽編號(hào): 079 周六一早,我坐上高鐵梁肿,趁周末蜓陌,去替換多日來(lái)連續(xù)給大哥陪床的大嫂和侄子...
    九月流云閱讀 655評(píng)論 19 33