做者:Marius Schulzhtml
譯者:前端小智前端
來源:Marius Schulzgit
阿里雲最近在作活動,低至2折,真心以爲很划算了,能夠點擊本條內容或者連接進行參與: promotion.aliyun.com/ntms/yunpar…es6
騰訊雲最近在作活動,百款雲產品低至 1 折,能夠點擊本條內容或者連接進行參與github
爲了保證的可讀性,本文采用意譯而非直譯。web
TypeScript 1.8 引入了字符串字面量類型,用於將變量限制爲可能的字符串值的有限集。在 TypeScript 2.0 中,字面量類型再也不侷限於字符串。如下字面量類型已添加到類型系統中:typescript
接下來,來看看這個類型對應的一些事例。npm
下面的示例定義了兩個常量 TRUE
和 FALSE
,它們分別持有 true
和 false
值:json
const TRUE: true = true; // OK
const FALSE: false = false; // OK
複製代碼
試圖爲每一個局部變量分配相反的布爾值會致使類型錯誤:promise
const TRUE: true = false;
// Error: Type 'false' is not assignable to type 'true'
const FALSE: false = true;
// Error: Type 'true' is not assignable to type 'false'
複製代碼
隨着 boolean 字面類型的引入,預約義的 boolean 類型如今等價於 true | false
的聯合類型:
let value: true | false; // Type boolean
複製代碼
雖然 boolean 字面量類型在隔離時不多有用,但它們與標記聯合類型和基於控制流的類型分析結合使用時很是有效。例如,能夠定義一個泛型 Result <T>
類型,該類型要麼包含一個類型爲 T
的值,要麼包含一個類型爲 string
的錯誤消息,以下所示
type Result<T> =
| { success: true; value: T }
| { success: false; error: string };
複製代碼
這是一個接受參數的函數:
function parseEmailAddress(
input: string | null | undefined
): Result<string> {
// 若是 input 爲 null,undefined 或空字符串
//(全部都是虛假的值),就直接返回。
if (!input) {
return {
success: false,
error: "The email address cannot be empty."
};
}
// 咱們只檢查 input 是否與模式匹配
// <something> @ <something> . <something>
// 保持簡單,正確驗證電子郵件地址
if (!/^\S+@\S+\.\S+$/.test(input)) {
return {
success: false,
error: "The email address has an invalid format."
};
}
return {
success: true,
value: input
};
}
複製代碼
請注意,啓用 strictNullChecks
選項後,string
是不可爲 null
的類型。爲了使函數的 input
參數接受可爲 null
的類型的值,必須在聯合類型中明確包含 null
和undefined
類型。
咱們如今能夠像下面這樣調用 parseEmailFunction
:
const parsed = parseEmailAddress("example@example.com");
if (parsed.success) {
parsed.value; // OK
parsed.error; // Error
} else {
parsed.value; // Error
parsed.error; // OK
}
複製代碼
請注意,某些屬性訪問表達式用紅色波浪線下劃線:
這樣作的好處是,編譯器僅在檢查了 parsed.success
後才容許我們使用value
或error
屬性:
若是 parsed.success
爲 true
,則 parsed
的類型必須爲 { success: true; value: string }
。在這種狀況下,我們能夠訪問 value
,但不能訪問 error
。
若是 parsed.success
爲 false
,則 parsed
的類型必須爲 { success: false; error: string }
。在這種狀況下,我們能夠訪問 error
,但不能訪問 value
。
與字符串字面量類型相似,咱們能夠將數值變量限制爲已知值的有限集
let zeroOrOne: 0 | 1;
zeroOrOne = 0;
// OK
zeroOrOne = 1;
// OK
zeroOrOne = 2;
// 錯誤:類型 '2' 不能分配給類型 '0 | 1'
複製代碼
在實踐中,咱們能夠在處理端口號時使用數字字面量。不安全的 HTTP 使用端口 80
,而 HTTPS 使用端口 443
。我們能夠編寫一個 getPort
函數,並在其函數簽名中編碼僅有的兩個可能的返回值
function getPort(scheme: "http" | "https"): 80 | 443 {
switch (scheme) {
case: "http":
return 80;
case: "https":
return 443;
}
}
const httpPort = getPort('http'); // Type 80 | 443
複製代碼
若是咱們將字面量類型與 TypeScript 的函數重載結合起來,那就更有趣了。這樣,咱們能夠爲 getPort
函數的不一樣重載提供更具體的類型。
function getPort(scheme: "http"): 80;
function getPort(scheme: "https"): 443;
function getPort(scheme: "http" | "https"): 80 | 443 {
switch (scheme) {
case "http":
return 80;
case "https":
return 443;
}
}
const httpPort = getPort("http"); // Type 80
const httpsPort = getPort("https"); // Type 443
複製代碼
如今,當返回的時候與比較的值永遠都不會相同的狀況下,編輯器會提示咱們,例如,將 httpPort
與值 443
進行比較時:
因爲 httpPort
的類型爲 80
,所以它始終包含值 80
,該值固然永遠不會等於值 443
。在這種狀況下,TypeScript 編譯器能夠幫助我們檢測錯誤的邏輯和無效的代碼。
最後,我們還可使用枚舉做爲字面量類型。繼續前面的示例,實現一個給定端口(80
或443
)映射到相應方案(分別爲 HTTP
或 HTTPS
)的函數。爲此,咱們首先聲明一個const enum
,它對兩個端口號進行構建:
const enum HttpPort {
Http = 80,
Https = 443
}
複製代碼
如今是 getScheme
函數,再次使用函數重載來實現專門的類型註解:
function getScheme(port: HttpPort.Http): "http";
function getScheme(port: HttpPort.Https): "https";
function getScheme(port: HttpPort): "http" | "https" {
switch (port) {
case HttpPort.Http:
return "http";
case HttpPort.Https:
return "https";
}
}
const scheme = getScheme(HttpPort.Http);
// Type "http"
複製代碼
常量枚舉沒有運行時表現形式(除非提供了preserveConstEnums
編譯器選項),也就是說,enum
用例的常量值將被內聯到使用它們的任何地方。下面是通過編譯的 JS 代碼,去掉了註解:
function getScheme(port) {
switch (port) {
case 80:
return "http";
case 443:
return "https";
}
}
var scheme = getScheme(80);
複製代碼
是否是超級簡潔?
TypeScript 2.0 讓我們以更細粒度地控制項目中包含哪些內置 API 聲明。之前,只有在的項目配置 ES6 相關的包才能訪問 ES6 Api
。如今,內置的標準庫聲明已經模塊化,TypeScript 容許咱們選擇包含哪一種類型聲明。
JS 標準庫的類型聲明被劃分爲一組 API 組。 2016 年 11 月下旬撰寫本文時,定義瞭如下組
能夠經過 --lib
命令行選項或 tsconfig.json
中的 lib
屬性將上述組的任何子集傳遞給TypeScript 編譯器。TypeScript 將只注入你指定的類型;也就是說,它會將全部其餘 API 組視爲不存在於你的的環境中。
若是未明確提供 lib
選項,則 TypeScript 將隱式注入Web開發所需的API組。
注意:若是--lib
沒有指定默認庫。默認庫是
["dom", "es5", "scripthost"]
["dom", "es6", "dom.iterable", "scripthost"]
假設你正在處理一個 target
爲 es5
項目,爲了讓它能在全部主流瀏覽器中運行。你的tsconfig.json
多是這樣的:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"strictNullChecks": true
}
}
複製代碼
由於 lib
選項沒有指定,因此默認狀況下 TypeScript 會注入 API 組 "dom"
、"es5"
和"scripthost"
。如今但願在項目中使用ES6 中原生的 Pormise
。這些在 ES5 中並無,因此我們須要安裝一個 polyfill
來讓咱們的代碼在舊的瀏覽器中運行:
npm install --save es6-promise
複製代碼
而後能夠在入口文件中導入對應的庫
import "es6-promise";
複製代碼
有了這個 polyfill,如今就能夠在應用程序中使用 Promise
,代碼也能夠正常運行。然而,TypeScript 會給你一個編譯時錯誤: Cannot find the name 'Promise'
。這是由於 Promise
的類型聲明不包含在任何注入的 API 組中。
咱要讓 TypeScript 知道 Promise
會在運行時存在,這就是 lib
編譯器選項發揮做用的地方:
注意,一旦覆蓋了默認值,就必須顯式地提供全部API組,以下所示:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"strictNullChecks": true,
"lib": ["dom", "es5", "es2015.promise"]
}
}
複製代碼
如今編輯器就不會在報錯了:
原文:
mariusschulz.com/blog/more-l… mariusschulz.com/blog/built-…
阿里雲最近在作活動,低至2折,有興趣能夠看看:promotion.aliyun.com/ntms/yunpar…
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
由於篇幅的限制,今天的分享只到這裏。若是你們想了解更多的內容的話,能夠去掃一掃每篇文章最下面的二維碼,而後關注我們的微信公衆號,瞭解更多的資訊和有價值的內容。