typescript返回值類型和參數(shù)類型的具體使用
返回值類型
在 JavaScript 中,我們知道一個函數(shù)可以沒有顯式 return,此時函數(shù)的返回值應該是 undefined:
function fn() { // TODO } console.log(fn()); // => undefined
需要注意的是,在 TypeScript 中,如果我們顯式聲明函數(shù)的返回值類型為 undfined,將會得到如下所示的錯誤提醒。
function fn(): undefined { // ts(2355) A function whose declared type is neither 'void' nor 'any' must return a value // TODO }
此時,正確的做法是使用 void 類型來表示函數(shù)沒有返回值的類型(這是“廢柴” void 類型唯一有用的場景),示例如下:
function fn1(): void { } fn1().doSomething(); // ts(2339) Property 'doSomething' does not exist on type 'void'
我們可以使用類似定義箭頭函數(shù)的語法來表示函數(shù)類型的參數(shù)和返回值類型,此時=> 類型僅僅用來定義一個函數(shù)類型而不用實現(xiàn)這個函數(shù)。
需要注意的是,這里的=>與 ES6 中箭頭函數(shù)的=>有所不同。TypeScript 函數(shù)類型中的=>用來表示函數(shù)的定義,其左側是函數(shù)的參數(shù)類型,右側是函數(shù)的返回值類型;而 ES6 中的=>是函數(shù)的實現(xiàn)。
在對象(即接口類型)中,除了使用這種聲明語法,我們還可以使用類似對象屬性的簡寫語法來聲明函數(shù)類型的屬性,如:
interface Entity { add: (a: number, b: number) => number; del(a: number, b: number): number; } const entity: Entity = { add: (a, b) => a + b, del(a, b) { return a - b; }, };
在某種意義上來說,這兩種形式都是等價的。但是很多時候,我們不必或者不能顯式地指明返回值的類型,這就涉及可缺省和可推斷的返回值類型的講解。
可缺省和可推斷的返回值類型
幸運的是,函數(shù)返回值的類型可以在 TypeScript 中被推斷出來,即可缺省。
函數(shù)內(nèi)是一個相對獨立的上下文環(huán)境,我們可以根據(jù)入?yún)χ导庸び嬎?,并返回新的值。從類型層面看,我們也可以通過類型推斷加工計算入?yún)⒌念愋停⒎祷匦碌念愋?,示例如下?/p>
function computeTypes(one: string, two: number) { const nums = [two]; const strs = [one] return { nums, strs } // 返回 { nums: number[]; strs: string[] } 的類型 }
請記?。哼@是一個很重要也很有意思的特性,函數(shù)返回值的類型推斷結合泛型可以實現(xiàn)特別復雜的類型推斷,比如 Redux Model 中 State、Reducer、Effect 類型的關聯(lián)。
一般情況下,TypeScript 中的函數(shù)返回值類型是可以缺省和推斷出來的,但是有些特例需要我們顯式聲明返回值類型,比如 Generator 函數(shù)的返回值。
Generator 函數(shù)的返回值
ES6 中新增的 Generator 函數(shù)在 TypeScript 中也有對應的類型定義。
Generator 函數(shù)返回的是一個 Iterator 迭代器對象,我們可以使用 Generator 的同名接口泛型或者 Iterator 的同名接口泛型表示返回值的類型(Generator 類型繼承了 Iterator 類型),示例如下:
type AnyType = boolean; type AnyReturnType = string; type AnyNextType = number; function *gen(): Generator<AnyType, AnyReturnType, AnyNextType> { const nextValue = yield true; // nextValue 類型是 number,yield 后必須是 boolean 類型 return `${nextValue}`; // 必須返回 string 類型 }
注意:TypeScript 3.6 之前的版本不支持指定 next、return 的類型,所以在某些有點歷史的代碼中,我們可能會看到 Generator 和 Iterator 類型不一樣的表述。
參數(shù)類型
關于 JS 中函數(shù)的參數(shù),在es6之后,統(tǒng)共可以分為:可選參數(shù)、默認參數(shù)、剩余參數(shù) 幾個特性。
可選參數(shù)和默認參數(shù)
在實際工作中,我們可能經(jīng)常碰到函數(shù)參數(shù)可傳可不傳的情況,當然 TypeScript 也支持這種函數(shù)類型表達,如下代碼所示:
function log(x?: string) { return x; } log(); // => undefined log('hello world'); // => hello world
在上述代碼中,我們在類型標注的:前添加?表示 log 函數(shù)的參數(shù) x 就是可缺省的。
也就是說參數(shù) x 的類型可能是 undefined(第 5 行調(diào)用 log 時不傳入實參)類型或者是 string 類型(第 6 行調(diào)用 log 傳入 'hello world' 實參),那是不是意味著可缺省和類型是 undefined 等價呢?
function log(x?: string) { console.log(x); } function log1(x: string | undefined) { console.log(x); } log(); log(undefined); log1(); // ts(2554) Expected 1 arguments, but got 0 log1(undefined);
顯而易見:這里的 ?: 表示參數(shù)可以缺省、可以不傳,但如果傳則一定是string類型。也就是說調(diào)用函數(shù)時,我們可以不顯式傳入?yún)?shù)。但是,如果我們聲明了參數(shù)類型為 xxx | undefined,就表示函數(shù)參數(shù)是不可缺省且類型必須是 xxx 或者 undfined。
因此,在上述代碼中,log1 函數(shù)如果不顯示傳入函數(shù)的參數(shù),TypeScript 就會報一個 ts(2554) 的錯誤,即函數(shù)需要 1 個參數(shù),但是我們只傳入了 0 個參數(shù)。
在 ES6 中支持函數(shù)默認參數(shù)的功能。而 TypeScript 會根據(jù)函數(shù)的默認參數(shù)的類型來推斷函數(shù)參數(shù)的類型,示例如下:
function log(x = 'hello') { console.log(x); } log(); // => 'hello' log('hi'); // => 'hi' log(1); // ts(2345) Argument of type '1' is not assignable to parameter of type 'string | undefined'
在上述示例中,根據(jù)函數(shù)的默認參數(shù) 'hello' ,TypeScript 推斷出了 x 的類型為 string | undefined。
當然,對于默認參數(shù),TypeScript 也可以顯式聲明參數(shù)的類型(一般默認參數(shù)的類型是參數(shù)類型的子集時,我們才需要這么做)。不過,此時的默認參數(shù)只起到參數(shù)默認值的作用,如下代碼所示:
function log1(x: string = 'hello') { console.log(x); } // ts(2322) Type 'string' is not assignable to type 'number' function log2(x: number = 'hello') { console.log(x); } log2(); log2(1); log2('1'); // ts(2345) Argument of type '"1"' is not assignable to parameter of type 'number | undefined'
上例函數(shù) log2 中,我們顯式聲明了函數(shù)參數(shù) x 的類型為 number,表示函數(shù)參數(shù) x 的類型可以不傳或者是 number 類型。因此,如果我們將默認值設置為字符串類型,編譯器就會拋出一個 ts(2322) 的錯誤。
同理,如果我們將函數(shù)的參數(shù)傳入了字符串類型,編譯器也會拋出一個 ts(2345) 的錯誤。
請再次注意:函數(shù)的默認參數(shù)類型必須是參數(shù)類型的子類型:
function log3(x: number | string = 'hello') { console.log(x); }
在上述代碼中,函數(shù) log3 的函數(shù)參數(shù) x 的類型為可選的聯(lián)合類型 number | string,但是因為默認參數(shù)字符串類型是聯(lián)合類型 number | string 的子類型,所以 TypeScript 也會檢查通過。
剩余參數(shù)
在 ES6 中,JavaScript 支持函數(shù)參數(shù)的剩余參數(shù),它可以把多個參數(shù)收集到一個變量中。同樣,在TypeScript 中也支持這樣的參數(shù)類型定義,如下代碼所示:
function sum(...nums: number[]) { return nums.reduce((a, b) => a + b, 0); } sum(1, 2); // => 3 sum(1, 2, 3); // => 6 sum(1, '2'); // ts(2345) Argument of type 'string' is not assignable to parameter of type 'number'
在上述代碼中,sum 是一個求和的函數(shù),...nums將函數(shù)的所有參數(shù)收集到了變量 nums 中,而 nums 的類型應該是 number[],表示所有被求和的參數(shù)是數(shù)字類型。因此,sum(1, '2') 拋出了一個 ts(2345) 的錯誤,因為參數(shù) '2' 并不是 number 類型。
如果我們將函數(shù)參數(shù) nums 聚合的類型定義為 (number | string)[],如下代碼所示:
function sum(...nums: (number | string)[]): number { return nums.reduce<number>((a, b) => a + Number(b), 0); } sum(1, '2', 3); // 6
那么,函數(shù)的每一個參數(shù)的類型就是聯(lián)合類型 number | string,因此 sum(1, '2', 3) 的類型檢查也就通過了。
typescript中的常見報錯:
- ts(2322)是一個靜態(tài)類型檢查的錯誤,在注解的類型和賦值的類型不同的時候就會拋出這個錯誤
- ts(2355) :簡單來說就是:函數(shù)必須有一個返回值(報錯翻譯:聲明類型既不是void也不是any的函數(shù)必須返回一個值)
- ts(2339): 在TypeScript中如果按JS的方式去獲取對象屬性時,可能會遇到。它表示Typescript在執(zhí)行代碼檢查時在該對象沒有定義相應屬性。解決方法有 —— 直接設置對象為any、對象斷言為any、將屬性.獲取方式改為數(shù)組式獲取三種
- ts(2345):參數(shù)類型與預期不符
- ts(2554):參數(shù)個數(shù)與預期不符
到此這篇關于typescript返回值類型和參數(shù)類型的具體使用的文章就介紹到這了,更多相關typescript返回值類型和參數(shù)類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳談js中window.location.search的用法和作用
下面小編就為大家?guī)硪黄斦刯s中window.location.search的用法和作用。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02解決layer.confirm快速點擊會重復觸發(fā)事件的問題
今天小編就為大家分享一篇解決layer.confirm快速點擊會重復觸發(fā)事件的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09一個友好的.改善的 Object.prototype.toString的實現(xiàn)
一個友好的.改善的 Object.prototype.toString的實現(xiàn)...2007-04-04詳解ES6之用let聲明變量以及l(fā)et loop機制
本篇文章主要介紹了詳解ES6之用let聲明變量以及l(fā)et loop機制,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07