成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一文學(xué)懂 TypeScript 的類型

lucas / 709人閱讀

摘要:如果屬性的值不能是,那么它必須在構(gòu)造函數(shù)中進(jìn)行初始化。為帶來(lái)了額外的層靜態(tài)類型。類型檢查可確保這些預(yù)測(cè)能夠?qū)崿F(xiàn)。元素不一定具有相同的類型。相反,在中,和由多帶帶的不相交類型處理。類型存在于元級(jí)別。將傳遞給的構(gòu)造函數(shù)。

翻譯:瘋狂的技術(shù)宅
原文:http://2ality.com/2018/04/typ...

本文首發(fā)微信公眾號(hào):jingchengyideng
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章

你將學(xué)到什么

閱讀本文后,你應(yīng)該能夠理解以下代碼的含義:

interface Array {
  concat(...items: Array): T[];
  reduce(
    callback: (state: U, element: T, index: number, array: T[]) => U,
    firstState?: U): U;
  ···
}

如果你認(rèn)為這段代碼非常神秘 —— 那么我同意你的意見。但是(我希望證明)這些符號(hào)還是相對(duì)容易學(xué)習(xí)的。一旦你能理解它們,就能馬上全面、精確的理解這種代碼,從而無(wú)需再去閱讀冗長(zhǎng)的英文說(shuō)明。

運(yùn)行代碼案例

TypeScript 有一個(gè)在線運(yùn)行環(huán)境。為了得到最全面的信息,你應(yīng)該在 “Options” 菜單中打開所有選項(xiàng)開關(guān)。這相當(dāng)于在 --strict 模式下運(yùn)行TypeScript編譯器。

關(guān)于類型檢查的詳細(xì)說(shuō)明

我在用 TypeScript 時(shí)總是喜歡打開 --strict 開關(guān)設(shè)置。沒有它,程序可能會(huì)稍微好寫一點(diǎn),但是你也失去了靜態(tài)類型檢查的好處。目前此設(shè)置能夠開啟以下子設(shè)置:

--noImplicitAny:如果 TypeScript 無(wú)法推斷類型,則必須指定它。這主要用于函數(shù)和方法的參數(shù):使用此設(shè)置,你必須對(duì)它們進(jìn)行注釋。

--noImplicitThis:如果 this 的類型不清楚則會(huì)給出提示信息。

--alwaysStrict:盡可能使用 JavaScript 的嚴(yán)格模式。

--strictNullChecksnull 不屬于任何類型(除了它自己的類型,null),如果它是可接受的值,則必須明確指定。

--strictFunctionTypes:對(duì)函數(shù)類型更加嚴(yán)格的檢查。

--strictPropertyInitialization:如果屬性的值不能是 undefined ,那么它必須在構(gòu)造函數(shù)中進(jìn)行初始化。

更多信息:TypeScript 手冊(cè)中的“編譯器選項(xiàng)”一章。

類型

在本文中,我們把類型看作是一組值的集合。 JavaScript 語(yǔ)言(不是TypeScript!)有7種類型:

Undefined:具有唯一元素 undefined 的集合。

Null:具有唯一元素“null”的集合。

Boolean:具有兩個(gè)元素 falsetrue 的集合。

Number:所有數(shù)字的集合。

String:所有字符串的集合。

Symbol:所有符號(hào)的集合。

Object:所有對(duì)象的集合(包括函數(shù)和數(shù)組)。

所有這些類型都是 dynamic:可以用在運(yùn)行時(shí)。

TypeScript 為 JavaScript 帶來(lái)了額外的層:靜態(tài)類型。這些僅在編譯或類型檢查源代碼時(shí)存在。每個(gè)存儲(chǔ)位置(變量或?qū)傩裕┒加幸粋€(gè)靜態(tài)類型,用于預(yù)測(cè)其動(dòng)態(tài)值。類型檢查可確保這些預(yù)測(cè)能夠?qū)崿F(xiàn)。還有很多可以進(jìn)行 靜態(tài) 檢查(不運(yùn)行代碼)的東西。例如,如果函數(shù) f(x) 的參數(shù) x 是靜態(tài)類型 number,則函數(shù)調(diào)用 f("abc") 是非法的,因?yàn)閰?shù) "abc" 是錯(cuò)誤的靜態(tài)類型。

類型注釋

變量名后的冒號(hào)開始 類型注釋:冒號(hào)后的類型簽名用來(lái)描述變量可以接受的值。例如以代碼告訴 TypeScript 變量 “x” 只能存儲(chǔ)數(shù)字:

let x: number;

你可能想知道用 undefined 去初始化 x 是不是違反了靜態(tài)類型。 TypeScript 不會(huì)允許這種情況出現(xiàn),因?yàn)樵跒樗x值之前不允許操作 x。

類型推斷

即使在 TypeScript 中每個(gè)存儲(chǔ)位置都有靜態(tài)類型,你也不必總是明確的去指定它。 TypeScript 通??梢詫?duì)它的類型進(jìn)行推斷。例如如果你寫下這行代碼:

let x = 123;

然后 TypeScript 會(huì)推斷出 x 的靜態(tài)類型是 number。

類型描述

在類型注釋的冒號(hào)后面出現(xiàn)的是所謂的類型表達(dá)式。這些范圍從簡(jiǎn)單到復(fù)雜,并按如下方式創(chuàng)建。

基本類型是有效的類型表達(dá)式:

對(duì)應(yīng) JavaScript 動(dòng)態(tài)類型的靜態(tài)類型:

- `undefined`, `null`
- `boolean`, `number`, `string`
- `symbol`
- `object`

注意:值 undefined 與類型 undefined(取決于所在的位置)

TypeScript 的特定類型:

Array(從技術(shù)上講不是 JS 中的類型)

any(所有值的類型)

等等其他類型

請(qǐng)注意,“undefined作為值“ 和 ”undefined作為類型” 都寫做 undefined。根據(jù)你使用它的位置,被解釋為值或類型。 null 也是如此。

你可以通過類型運(yùn)算符對(duì)基本類型進(jìn)行組合的方式來(lái)創(chuàng)建更多的類型表達(dá)式,這有點(diǎn)像使用運(yùn)算符 union)和intersection()去合并集合。

下面介紹 TypeScript 提供的一些類型運(yùn)算符。

數(shù)組類型

數(shù)組在 JavaScript 中扮演以下兩個(gè)角色(有時(shí)是兩者的混合):

列表:所有元素都具有相同的類型。數(shù)組的長(zhǎng)度各不相同。

元組:數(shù)組的長(zhǎng)度是固定的。元素不一定具有相同的類型。

數(shù)組作為列表

數(shù)組 arr 被用作列表有兩種方法表示 ,其元素都是數(shù)字:

let arr: number[] = [];
let arr: Array = [];

通常如果存在賦值的話,TypeScript 就可以推斷變量的類型。在這種情況下,實(shí)際上你必須幫它解決類型問題,因?yàn)樵谑褂每諗?shù)組時(shí),它無(wú)法確定元素的類型。

稍后我們將回到尖括號(hào)表示法(Array)。

數(shù)組作為元組

如果你想在數(shù)組中存儲(chǔ)二維坐標(biāo)點(diǎn),那么就可以把這個(gè)數(shù)組當(dāng)作元組去用??瓷先ナ沁@個(gè)樣子:

let point: [number, number] = [7, 5];

在這種情況下,你不需要類型注釋。

另外一個(gè)例子是 Object.entries(obj) 的返回值:一個(gè)帶有一個(gè) [key,value] 對(duì)的數(shù)組,它用于描述 obj 的每個(gè)屬性。

> Object.entries({a:1, b:2})
[ [ "a", 1 ], [ "b", 2 ] ]

Object.entries() 的返回值類型是:

Array<[string, any]>
函數(shù)類型

以下是函數(shù)類型的例子:

(num: number) => string

這個(gè)類型是一個(gè)函數(shù),它接受一個(gè)數(shù)字類型參數(shù)并且返回值為字符串。在類型注釋中使用這種類型(String 在這里是個(gè)函數(shù))的例子:

const func: (num: number) => string = String;

同樣,我們一般不會(huì)在這里使用類型注釋,因?yàn)?TypeScript 知道 String 的類型,因此可以推斷出 func 的類型。

以下代碼是一個(gè)更實(shí)際的例子:

function stringify123(callback: (num: number) => string) {
  return callback(123);
}

由于我們使用了函數(shù)類型來(lái)描述 stringify123() 的參數(shù) callback,所以TypeScript 拒絕以下函數(shù)調(diào)用。

f(Number);

但它接受以下函數(shù)調(diào)用:

f(String);
函數(shù)聲明的返回類型

對(duì)函數(shù)的所有參數(shù)進(jìn)行注釋是一個(gè)很好的做法。你還可以指定返回值類型(不過 TypeScript 非常擅長(zhǎng)去推斷它):

function stringify123(callback: (num: number) => string): string {
  const num = 123;
  return callback(num);
}
特殊返回值類型 void

void 是函數(shù)的特殊返回值類型:它告訴 TypeScript 函數(shù)總是返回 undefined(顯式或隱式):

function f1(): void { return undefined } // OK
function f2(): void { } // OK
function f3(): void { return "abc" } // error
可選參數(shù)

標(biāo)識(shí)符后面的問號(hào)表示該參數(shù)是可選的。例如:

function stringify123(callback?: (num: number) => string) {
  const num = 123;
  if (callback) {
    return callback(num); // (A)
  }
  return String(num);
}

--strict 模式下運(yùn)行 TypeScript 時(shí),如果事先檢查時(shí)發(fā)現(xiàn) callback 沒有被省略,它只允許你在 A 行進(jìn)行函數(shù)調(diào)用。

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

TypeScript支持 ES6 參數(shù)默認(rèn)值:

function createPoint(x=0, y=0) {
  return [x, y];
}

默認(rèn)值可以使參數(shù)可選。通??梢允÷灶愋妥⑨?,因?yàn)?TypeScript 可以推斷類型。例如它可以推斷出 xy 都是 number 類型。

如果要添加類型注釋,應(yīng)該這樣寫:

function createPoint(x:number = 0, y:number = 0) {
  return [x, y];
}
rest 類型

你還可以用 ES6 rest operator 進(jìn)行 TypeScript 參數(shù)定義。相應(yīng)參數(shù)的類型必須是數(shù)組:

function joinNumbers(...nums: number[]): string {
    return nums.join("-");
}
joinNumbers(1, 2, 3); // "1-2-3"
Union

在JavaScript中,有時(shí)候變量會(huì)是有幾種類型之中的一種。要描述這些變量,可以使用 union types。例如,在下面的代碼中,xnull 類型或 number 類型:

let x = null;
x = 123;

x 的類型可以描述為 null | number

let x: null|number = null;
x = 123;

類型表達(dá)式 s | t 的結(jié)果是類型 st 在集合理論意義上的聯(lián)合(正如我們之前看到的那樣,兩個(gè)集合)。

下面讓我們重寫函數(shù) stringify123():這次我們不希望參數(shù) callback 是可選的。應(yīng)該總是調(diào)用它。如果調(diào)用者不想傳入一個(gè)函數(shù),則必須顯式傳遞 null。實(shí)現(xiàn)如下。

function stringify123(
  callback: null | ((num: number) => string)) {
  const num = 123;
  if (callback) { // (A)
    return callback(123); // (B)
  }
  return String(num);
}

請(qǐng)注意,在行 B 進(jìn)行函數(shù)調(diào)用之前,我們必須再次檢查 callback 是否真的是一個(gè)函數(shù)(行A)。如果沒有檢查,TypeScript 將會(huì)報(bào)告錯(cuò)誤。

Optional 與 undefined|T

類型為 T 的可選參數(shù)和類型為 undefined|T 的參數(shù)非常相似。 (另外對(duì)于可選屬性也是如此。)

主要區(qū)別在于你可以省略可選參數(shù):

function f1(x?: number) { }
f1(); // OK
f1(undefined); // OK
f1(123); // OK

But you can’t omit parameters of type
但是你不能省略 undefined|T 類型的參數(shù):

function f2(x: undefined | number) { }
f2(); // error
f2(undefined); // OK
f2(123); // OK
nullundefined 通常不包含在類型中

在許多編程語(yǔ)言中,null 是所有類型的一部分。例如只要 Java 中的參數(shù)類型為 String,就可以傳遞 null 而Java 不會(huì)報(bào)錯(cuò)。

相反,在TypeScript中,undefinednull 由多帶帶的不相交類型處理。如果你想使它們生效,必須要有一個(gè)類型聯(lián)合,如 undefined|stringnull|string。

對(duì)象

與Arrays類似,對(duì)象在 JavaScript 中扮演兩個(gè)角色(偶爾混合和/或更加動(dòng)態(tài)):

記錄:在開發(fā)時(shí)已知的固定數(shù)量的屬性。每個(gè)屬性可以有不同的類型。

字典:在開發(fā)時(shí)名稱未知的任意數(shù)量的屬性。所有屬性鍵(字符串和/或符號(hào))都具有相同的類型,屬性值也是如此。

我們將在本文章中忽略 object-as-dictionaries。順便說(shuō)一句,無(wú)論如何,map 通常是比字典的更好選擇。

通過接口描述 objects-as-records

接口描述 objects-as-records 。例如:

interface Point {
  x: number;
  y: number;
}

TypeScript 類型系統(tǒng)的一大優(yōu)勢(shì)在于它的結(jié)構(gòu)上,而不是在命名上。也就是說(shuō),接口 Point 能夠匹配適當(dāng)結(jié)構(gòu)的所有對(duì)象:

function pointToString(p: Point) {
  return `(${p.x}, ${p.y})`;
}
pointToString({x: 5, y: 7}); // "(5, 7)"

相比之下,Java 的標(biāo)稱類型系統(tǒng)需要類來(lái)實(shí)現(xiàn)接口。

可選屬性

如果可以省略屬性,則在其名稱后面加上一個(gè)問號(hào):

interface Person {
  name: string;
  company?: string;
}
方法

接口內(nèi)還可以包含方法:

interface Point {
  x: number;
  y: number;
  distance(other: Point): number;
}
類型變量和泛型類型

使用靜態(tài)類型,可以有兩個(gè)級(jí)別:

值存在于對(duì)象級(jí)別。

類型存在于元級(jí)別。

同理:

普通變量定義在對(duì)象級(jí)別之上。

類型變量存在于元級(jí)別之上。它們是值為類型的變量。

普通變量通過 const,let 等引入。類型變量通過尖括號(hào)( <> )引入。例如以下代碼包含類型變量 T,通過 引入。

interface Stack {
  push(x: T): void;
  pop(): T;
}

你可以看到類型參數(shù) TStack 的主體內(nèi)出現(xiàn)兩次。因此,該接口可以直觀地理解如下:

Stack 是一堆值,它們都具有給定的類型 T。每當(dāng)你提到 Stack 時(shí),必須寫 T。接下來(lái)我們會(huì)看到究竟該怎么用。

方法 .push() 接受類型為 T 的值。

方法 .pop() 返回類型為 T 的值。

如果使用 Stack,則必須為 T 指定一個(gè)類型。以下代碼顯示了一個(gè)虛擬棧,其唯一目的是匹配接口。

const dummyStack: Stack = {
  push(x: number) {},
  pop() { return 123 },
};
例子:map

map 在 TypeScript 中的定義。例如:

const myMap: Map = new Map([
  [false, "no"],
  [true, "yes"],
]);
函數(shù)的類型變量

函數(shù)(和方法)也可以引入類型變量:

function id(x: T): T {
  return x;
}

你可以按以下方式使用此功能。

id(123);

由于類型推斷,還可以省略類型參數(shù):

id(123);
傳遞類型參數(shù)

函數(shù)可以將其她的類型參數(shù)傳給接口、類等:

function fillArray(len: number, elem: T) {
  return new Array(len).fill(elem);
}

類型變量 T 在這段代碼中出現(xiàn)三次:

fillArray:引入類型變量

elem:T:使用類型變量,從參數(shù)中選擇它。

Array:將 T 傳遞給 Array 的構(gòu)造函數(shù)。

這意味著:我們不必顯式指定Array的類型 T —— 它是從參數(shù) elem中推斷出來(lái)的:

const arr = fillArray(3, "*");
  // Inferred type: string[]
總結(jié)

讓我們用前面學(xué)到的知識(shí)來(lái)理解最開始看到的那段代碼:

interface Array {
  concat(...items: Array): T[];
  reduce(
    callback: (state: U, element: T, index: number, array: T[]) => U,
    firstState?: U): U;
  ···
}

這是一個(gè)Array的接口,其元素類型為 T,每當(dāng)使用這個(gè)接口時(shí)必須填寫它:

方法.concat()有零個(gè)或多個(gè)參數(shù)(通過 rest 運(yùn)算符定義)。其中每一個(gè)參數(shù)中都具有類型 T[]|T。也就是說(shuō),它是一個(gè) T 類型的數(shù)組或是一個(gè) T 值。

方法.reduce() 引入了自己的類型變量 UU 表示以下實(shí)體都具有相同的類型(你不需要指定,它是自動(dòng)推斷的):

Parameter state of callback() (which is a function)

statecallback() 的參數(shù)(這是一個(gè)函數(shù))

Result of callback()

callback()的返回

.reduce()的可選參數(shù) firstState

Result of .reduce()

.reduce()的返回

callback 還將獲得一個(gè) element 參數(shù),其類型與 Array 元素具有相同的類型 T,參數(shù) index 是一個(gè)數(shù)字,參數(shù) arrayT 的值。

擴(kuò)展閱讀

書籍(免費(fèi)在線閱讀):“Exploring ES6”

ECMAScript規(guī)范中的“ECMAScript語(yǔ)言類型”。

“TypeScript 手冊(cè)”:寫得非常好,并解釋了TypeScript支持的各種其他類型和類型的運(yùn)算符。

GitHub 上有 完整 ECMAScript 標(biāo)準(zhǔn)庫(kù)的類型定義。這是練習(xí)類型符號(hào)的簡(jiǎn)單方法。

本文首發(fā)微信公眾號(hào):jingchengyideng 歡迎掃描二維碼關(guān)注公眾號(hào),每天都給你推送新鮮的前端技術(shù)文章

歡迎繼續(xù)閱讀本專欄其它高贊文章:

12個(gè)令人驚嘆的CSS實(shí)驗(yàn)項(xiàng)目

世界頂級(jí)公司的前端面試都問些什么

CSS Flexbox 可視化手冊(cè)

過節(jié)很無(wú)聊?還是用 JavaScript 寫一個(gè)腦力小游戲吧!

從設(shè)計(jì)者的角度看 React

CSS粘性定位是怎樣工作的

一步步教你用HTML5 SVG實(shí)現(xiàn)動(dòng)畫效果

程序員30歲前月薪達(dá)不到30K,該何去何從

7個(gè)開放式的前端面試題

React 教程:快速上手指南

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102536.html

相關(guān)文章

  • 一篇文章帶你過一遍 TypeScript

    摘要:泛型通過在函數(shù)接口類變量名后使用定義。抽象類可以包括具體實(shí)現(xiàn)一個(gè)類只能繼承一個(gè)類,但是可以實(shí)現(xiàn)多個(gè)接口。該開源項(xiàng)目目前由社區(qū)進(jìn)行維護(hù)。通常通過中的字段,或者聲明文件進(jìn)行聲明。 TypeScript 是 Javascript 的一個(gè)超集,提高了代碼的可讀性和可維護(hù)性。Typescript 官網(wǎng)提供的文檔已經(jīng)相當(dāng)完善,但完整地看一遍需要一定的時(shí)間,本文試將 TypeScript 中要點(diǎn)提出...

    AlphaWallet 評(píng)論0 收藏0
  • 一文快速解讀ES6新特性

    摘要:是一項(xiàng)標(biāo)準(zhǔn),于年月獲得批準(zhǔn)。靜態(tài)限制在分配之前阻止使用。使用通用到基于自定義迭代器的迭代。迭代基于這些鴨子類型接口僅使用類型語(yǔ)法進(jìn)行展示生成器生成器使用和簡(jiǎn)化迭代器。生成器是迭代器的子類型,包括額外的和。 ECMAScript 2015是一項(xiàng)ECMAScript標(biāo)準(zhǔn),于2015年6月獲得批準(zhǔn)。 ES2015是該語(yǔ)言的重要更新,也是自2009年ES5標(biāo)準(zhǔn)化以來(lái)該語(yǔ)言的第一次重大更新?,F(xiàn)在...

    goji 評(píng)論0 收藏0
  • 從 JavaScript 到 TypeScript - 接口

    摘要:前面講泛型的時(shí)候,提到了接口。和泛型一樣,接口也是目前中并不存在的語(yǔ)法。不過可不吃這一套,所以這里通過注釋關(guān)閉了對(duì)該接口的命名檢查。這樣的接口不能由類實(shí)現(xiàn)。 前面講 泛型 的時(shí)候,提到了接口。和泛型一樣,接口也是目前 JavaScript 中并不存在的語(yǔ)法。 由于泛型語(yǔ)法總是附加在類或函數(shù)語(yǔ)法中,所以從 TypeScript 轉(zhuǎn)譯成 JavaScript 之后,至少還存在類和函數(shù)(只是...

    darkbaby123 評(píng)論0 收藏0
  • 平時(shí)積累前端資源,持續(xù)更新中。。。

    本文收集學(xué)習(xí)過程中使用到的資源。 持續(xù)更新中…… 項(xiàng)目地址 https://github.com/abc-club/f... 目錄 vue react react-native Weex typescript Taro nodejs 常用庫(kù) css js es6 移動(dòng)端 微信公眾號(hào) 小程序 webpack GraphQL 性能與監(jiān)控 高質(zhì)文章 趨勢(shì) 動(dòng)效 數(shù)據(jù)結(jié)構(gòu)與算法 js core 代碼規(guī)范...

    acrazing 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

lucas

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<