TypeScript的函數(shù)的類型

本文摘自

https://ts.xcatliu.com/basics/type-of-function


函數(shù)的類型

?函數(shù)是 JavaScript 中的一等公民?

函數(shù)聲明

在 JavaScript 中虐先,有兩種常見(jiàn)的定義函數(shù)的方式——函數(shù)聲明(Function Declaration)和函數(shù)表達(dá)式(Function Expression):

// 函數(shù)聲明(Function Declaration)
function sum(x, y) {
 return x + y;
}
?
// 函數(shù)表達(dá)式(Function Expression)
let mySum = function (x, y) {
 return x + y;
};

一個(gè)函數(shù)有輸入和輸出怨愤,要在 TypeScript 中對(duì)其進(jìn)行約束,需要把輸入和輸出都考慮到蛹批,其中函數(shù)聲明的類型定義較簡(jiǎn)單:

function sum(x: number, y: number): number {
 return x + y;
}

注意撰洗,輸入多余的(或者少于要求的)參數(shù),是不被允許的

function sum(x: number, y: number): number {
 return x + y;
}

sum(1, 2, 3);
?
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
function sum(x: number, y: number): number {
 return x + y;
}

sum(1);

// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.

函數(shù)表達(dá)式

如果要我們現(xiàn)在寫一個(gè)對(duì)函數(shù)表達(dá)式(Function Expression)的定義腐芍,可能會(huì)寫成這樣:

let mySum = function (x: number, y: number): number {
 return x + y;
};

這是可以通過(guò)編譯的差导,不過(guò)事實(shí)上猪勇,上面的代碼只對(duì)等號(hào)右側(cè)的匿名函數(shù)進(jìn)行了類型定義设褐,而等號(hào)左邊的 mySum,是通過(guò)賦值操作進(jìn)行類型推論而推斷出來(lái)的埠对。如果需要我們手動(dòng)給 mySum 添加類型络断,則應(yīng)該是這樣:

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
 return x + y;
};

注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>

在 TypeScript 的類型定義中项玛,=> 用來(lái)表示函數(shù)的定義貌笨,左邊是輸入類型,需要用括號(hào)括起來(lái)襟沮,右邊是輸出類型锥惋。

在 ES6 中,=> 叫做箭頭函數(shù)开伏,應(yīng)用十分廣泛膀跌,可以參考 ES6 中的箭頭函數(shù)

用接口定義函數(shù)的形狀

我們也可以使用接口的方式來(lái)定義一個(gè)函數(shù)需要符合的形狀:

interface SearchFunc {
 (source: string, subString: string): boolean;
}
?
let mySearch: SearchFunc;

mySearch = function(source: string, subString: string) {
 return source.search(subString) !== -1;
}

可選參數(shù)

前面提到固灵,輸入多余的(或者少于要求的)參數(shù)捅伤,是不允許的。那么如何定義可選的參數(shù)呢巫玻?

與接口中的可選屬性類似丛忆,我們用 ? 表示可選的參數(shù):

function buildName(firstName: string, lastName?: string) {
 if (lastName) {
 return firstName + ' ' + lastName;
 } else {
 return firstName;
 }
}

let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

需要注意的是祠汇,可選參數(shù)必須接在必需參數(shù)后面。換句話說(shuō)熄诡,可選參數(shù)后面不允許再出現(xiàn)必需參數(shù)了

function buildName(firstName?: string, lastName: string) {
 if (firstName) {
 return firstName + ' ' + lastName;
 } else {
 return lastName;
 }
}

let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');

// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.

參數(shù)默認(rèn)值

在 ES6 中可很,我們?cè)试S給函數(shù)的參數(shù)添加默認(rèn)值,TypeScript 會(huì)將添加了默認(rèn)值的參數(shù)識(shí)別為可選參數(shù)

function buildName(firstName: string, lastName: string = 'Cat') {
 return firstName + ' ' + lastName;
}

let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

此時(shí)就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了:

function buildName(firstName: string = 'Tom', lastName: string) {
 return firstName + ' ' + lastName;
}

let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

關(guān)于默認(rèn)參數(shù)凰浮,可以參考 ES6 中函數(shù)參數(shù)的默認(rèn)值我抠。

剩余參數(shù)

ES6 中,可以使用 ...rest 的方式獲取函數(shù)中的剩余參數(shù)(rest 參數(shù)):

function push(array, ...items) {
 items.forEach(function(item) {
 array.push(item);
 });
}

let a = [];
push(a, 1, 2, 3);

事實(shí)上袜茧,items 是一個(gè)數(shù)組菜拓。所以我們可以用數(shù)組的類型來(lái)定義它:

function push(array: any[], ...items: any[]) {
 items.forEach(function(item) {
 array.push(item);
 });
}

let a = [];
push(a, 1, 2, 3);

注意,rest 參數(shù)只能是最后一個(gè)參數(shù)惫周,關(guān)于 rest 參數(shù)尘惧,可以參考 ES6 中的 rest 參數(shù)康栈。

重載

重載允許一個(gè)函數(shù)接受不同數(shù)量或類型的參數(shù)時(shí)递递,作出不同的處理。

比如啥么,我們需要實(shí)現(xiàn)一個(gè)函數(shù) reverse登舞,輸入數(shù)字 123 的時(shí)候,輸出反轉(zhuǎn)的數(shù)字 321悬荣,輸入字符串 'hello' 的時(shí)候菠秒,輸出反轉(zhuǎn)的字符串 'olleh'

利用聯(lián)合類型氯迂,我們可以這么實(shí)現(xiàn):

function reverse(x: number | string): number | string {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
  }
}

然而這樣有一個(gè)缺點(diǎn)践叠,就是不能夠精確的表達(dá),輸入為數(shù)字的時(shí)候嚼蚀,輸出也應(yīng)該為數(shù)字禁灼,輸入為字符串的時(shí)候,輸出也應(yīng)該為字符串轿曙。

這時(shí)弄捕,我們可以使用重載定義多個(gè) reverse 的函數(shù)類型:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
  }
}

上例中,我們重復(fù)定義了多次函數(shù) reverse导帝,前幾次都是函數(shù)定義守谓,最后一次是函數(shù)實(shí)現(xiàn)。在編輯器的代碼提示中您单,可以正確的看到前兩個(gè)提示斋荞。

注意,TypeScript 會(huì)優(yōu)先從最前面的函數(shù)定義開(kāi)始匹配虐秦,所以多個(gè)函數(shù)定義如果有包含關(guān)系平酿,需要優(yōu)先把精確的定義寫在前面讯檐。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市染服,隨后出現(xiàn)的幾起案子别洪,更是在濱河造成了極大的恐慌,老刑警劉巖柳刮,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挖垛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秉颗,警方通過(guò)查閱死者的電腦和手機(jī)痢毒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蚕甥,“玉大人哪替,你說(shuō)我怎么就攤上這事」交常” “怎么了凭舶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)爱沟。 經(jīng)常有香客問(wèn)我帅霜,道長(zhǎng),這世上最難降的妖魔是什么呼伸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任身冀,我火速辦了婚禮,結(jié)果婚禮上括享,老公的妹妹穿的比我還像新娘搂根。我一直安慰自己,他們只是感情好铃辖,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布剩愧。 她就那樣靜靜地躺著,像睡著了一般澳叉。 火紅的嫁衣襯著肌膚如雪隙咸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天成洗,我揣著相機(jī)與錄音五督,去河邊找鬼。 笑死瓶殃,一個(gè)胖子當(dāng)著我的面吹牛充包,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼基矮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼淆储!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起家浇,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤本砰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后钢悲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體点额,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年莺琳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了还棱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惭等,死狀恐怖珍手,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辞做,我是刑警寧澤茫多,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布烘豹,位于F島的核電站龟梦,受9級(jí)特大地震影響位仁,放射性物質(zhì)發(fā)生泄漏晒杈。R本人自食惡果不足惜嫂伞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拯钻。 院中可真熱鬧帖努,春花似錦、人聲如沸粪般。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亩歹。三九已至匙监,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間小作,已是汗流浹背亭姥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顾稀,地道東北人达罗。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像静秆,于是被迫代替她去往敵國(guó)和親粮揉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巡李,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

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