導航:首頁 > 源碼編譯 > typescript編譯混淆

typescript編譯混淆

發布時間:2022-10-17 09:30:37

Ⅰ 如何編譯TypeScript

1)通過 File -> New-Project 新建項目
2)輸入必要信息,點擊 Ok 按鈕,創建後項目模板如下
3)app.js 依賴於 app.ts,默認的 app.ts 文件包含類和構造函數等等
4)TypeScript 文件將會被編譯為 javaScript (app.js),下面是編譯後的 JavaScript 代碼
5)在頁面中引用 JavaScript
6)構建或者重新構建項目時,你將看到提示是否重新編譯 TypeScript 的信息
7)在 proj 文件中有如下內容將會被自動編譯
8)運行此應用時會在頁面上顯示當前的日期和時間

Ⅱ typescript 怎麼混淆加密,編譯輸出js文件

選擇
configure
task
runner
自動創建
task.json
。該配置文件在工作空間的.vscode目錄下,這個目錄也是存放vscode配置的文件夾
vscode默認的task配置文件中給出了執行tsc

gulp模板配置。簡單介紹一下
task.json
的寫法
{"version":
"0.1.0",//
要使用的命令或者可執行文件的路徑"command":
"tsc",//
對應command參數,是否是一個命令,否則為執行文件路徑"isshellcommand":
true,//
是否在執行task任務時顯示控制台窗口"showoutput":
"always",//
對應command參數指定程序的參數"args":
["-p",
"src",
"--allowjs",
"-w"],//
不太明白這個,基本用不到"problemmatcher":
"$tsc",}

Ⅲ TypeScript 變數聲明

一直以來我們都是通過 var 關鍵字定義JavaScript變數。

大家都能理解,這里定義了一個名為 a 值為 10 的變數。

我們也可以在函數內部定義變數:

並且我們也可以在其它函數內部訪問相同的變數。

上面的例子里, g 可以獲取到 f 函數里定義的 a 變數。 每當 g 被調用時,它都可以訪問到 f 里的 a 變數。 即使當 g 在 f 已經執行完後才被調用,它仍然可以訪問及修改 a 。

這里很容易看出一些問題,里層的 for 循環會覆蓋變數 i ,因為所有 i 都引用相同的函數作用域內的變數。 有經驗的開發者們很清楚,這些問題可能在代碼審查時漏掉,引發無窮的麻煩。

快速的猜一下下面的代碼會返回什麼:

介紹一下, setTimeout 會在若干毫秒的延時後執行一個函數(等待其它代碼執行完畢)。

好吧,看一下結果:

很多JavaScript程序員對這種行為已經很熟悉了,但如果你很不解,你並不是一個人。 大多數人期望輸出結果是這樣:

還記得我們上面提到的捕獲變數嗎?

讓我們花點時間思考一下這是為什麼。 setTimeout 在若干毫秒後執行一個函數,並且是在 for 循環結束後。 for 循環結束後, i 的值為 10 。 所以當函數被調用的時候,它會列印出 10 !

一個通常的解決方法是使用立即執行的函數表達式(IIFE)來捕獲每次迭代時 i 的值:

這種奇怪的形式我們已經司空見慣了。 參數 i 會覆蓋 for 循環里的 i ,但是因為我們起了同樣的名字,所以我們不用怎麼改 for 循環體里的代碼。

主要的區別不在語法上,而是語義,我們接下來會深入研究。

這里我們定義了2個變數 a 和 b 。 a 的作用域是 f 函數體內,而 b 的作用域是 if 語句塊里。

關於 暫時性死區 的更多信息,查看這里Mozilla Developer Network.

在一個嵌套作用域里引入一個新名字的行為稱做 屏蔽 。 它是一把雙刃劍,它可能會不小心地引入新問題,同時也可能會解決一些錯誤。 例如,假設我們現在用 let 重寫之前的 sumMatrix 函數。

這個版本的循環能得到正確的結果,因為內層循環的 i 可以屏蔽掉外層循環的 i 。

通常 來講應該避免使用屏蔽,因為我們需要寫出清晰的代碼。 同時也有些場景適合利用它,你需要好好打算一下。

因為我們已經在 city 的環境里獲取到了 city ,所以就算 if 語句執行結束後我們仍然可以訪問它。

回想一下前面 setTimeout 的例子,我們最後需要使用立即執行的函數表達式來獲取每次 for 循環迭代里的狀態。 實際上,我們做的是為獲取到的變數創建了一個新的變數環境。 這樣做挺痛苦的,但是幸運的是,你不必在TypeScript里這樣做了。

會輸出與預料一致的結果:

這很好理解,它們引用的值是 不可變的

除非你使用特殊的方法去避免,實際上 const 變數的內部狀態是可修改的。 幸運的是,TypeScript允許你將對象的成員設置成只讀的。 介面一章有詳細說明。

使用最小特權原則,所有變數除了你計劃去修改的都應該使用 const 。 基本原則就是如果一個變數不需要對它寫入,那麼其它使用這些代碼的人也不能夠寫入它們,並且要思考為什麼會需要對這些變數重新賦值。 使用 const 也可以讓我們更容易的推測數據的流動。

跟據你的自己判斷,如果合適的話,與團隊成員商議一下。

Another TypeScript已經可以解析其它 ECMAScript 2015 特性了。 完整列表請參見 the article on the Mozilla Developer Network。 本章,我們將給出一個簡短的概述。

最簡單的解構莫過於數組的解構賦值了:

這創建了2個命名變數 first 和 second 。 相當於使用了索引,但更為方便:

作用於函數參數:

你可以在數組里使用 ... 語法創建剩餘變數:

當然,由於是JavaScript, 你可以忽略你不關心的尾隨元素:

或其它元素:

你也可以解構對象:

這通過 o.a and o.b 創建了 a 和 b 。 注意,如果你不需要 c 你可以忽略它。

注意,我們需要用括弧將它括起來,因為Javascript通常會將以 { 起始的語句解析為一個塊。

你可以在對象里使用 ... 語法創建剩餘變數:

你也可以給屬性以不同的名字:

這里的語法開始變得混亂。 你可以將 a: newName1 讀做 " a 作為 newName1 "。 方向是從左到右,好像你寫成了以下樣子:

令人困惑的是,這里的冒號 不是 指示類型的。 如果你想指定它的類型, 仍然需要在其後寫上完整的模式。

默認值可以讓你在屬性為 undefined 時使用預設值:

現在,即使 b 為 undefined , keepWholeObject 函數的變數 wholeObject 的屬性 a 和 b 都會有值。

但是,通常情況下更多的是指定默認值,解構默認值有些棘手。 首先,你需要在默認值之前設置其格式。

其次,你需要知道在解構屬性上給予一個默認或可選的屬性用來替換主初始化列表。 要知道 C 的定義有一個 b 可選屬性:

要小心使用解構。 從前面的例子可以看出,就算是最簡單的解構表達式也是難以理解的。 尤其當存在深層嵌套解構的時候,就算這時沒有堆疊在一起的重命名,默認值和類型註解,也是令人難以理解的。 解構表達式要盡量保持小而簡單。 你自己也可以直接使用解構將會生成的賦值表達式。

展開操作符正與解構相反。 它允許你將一個數組展開為另一個數組,或將一個對象展開為另一個對象。 例如:

這會令 bothPlus 的值為 [0, 1, 2, 3, 4, 5] 。 展開操作創建了 first 和 second 的一份淺拷貝。 它們不會被展開操作所改變。

你還可以展開對象:

search 的值為 { food: "rich", price: "$", ambiance: "noisy" } 。 對象的展開比數組的展開要復雜的多。 像數組展開一樣,它是從左至右進行處理,但結果仍為對象。 這就意味著出現在展開對象後面的屬性會覆蓋前面的屬性。 因此,如果我們修改上面的例子,在結尾處進行展開的話:

那麼, defaults 里的 food 屬性會重寫 food: "rich" ,在這里這並不是我們想要的結果。

對象展開還有其它一些意想不到的限制。 首先,它僅包含對象 自身的可枚舉屬性。 大體上是說當你展開一個對象實例時,你會丟失其方法:

其次,TypeScript編譯器不允許展開泛型函數上的類型參數。 這個特性會在TypeScript的未來版本中考慮實現。

Ⅳ typescript和js的區別是什麼

typescript和js的區別如下:

一:產生背景不同

1、TypeScript起源於使用JavaScript開發的大型項目。由於JavaScript語言本身的局限性,難以勝任和維護大型項目開發。因此微軟開發了TypeScript,使得其能夠勝任開發大型項目。

2、JavaScript在1995年由Netscape公司的BrendanEich,在網景導航者瀏覽器上首次設計實現而成。因為Netscape與Sun合作,Netscape管理層希望它外觀看起來像Java,因此取名為JavaScript。

二:功能不同

1、TypeScript是JavaScript的一個超集,而且本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程

2、JavaScript是一種基於對象的語言,可以創建對象同時使用現有對象。但是Javascript並不支持其它面向對象語言所具有的繼承和重載功能。

三:局限性不同

1、TypeScript擴展了JavaScript的語法,所以任何現有的JavaScript程序可以運行在TypeScript環境中。TypeScript是為大型應用的開發而設計,並且可以編譯為JavaScript。

TypeScript支持為已存在的JavaScript庫添加類型信息的頭文件,擴展了它對於流行庫的支持,如jQuery,MongoDB,Node.js和D3.js等。

2、由於JavaScript語言發展的較早,也較為成熟,所以仍有一大批開發人員堅持使用他們熟悉的腳本語言JavaScript,而不是學習TypeScript。

TypeScript代碼需要被編譯(輸出JavaScript代碼),這是TypeScript代碼執行時的一個額外的步驟。

Ⅳ TypeScript 速成教程

Typescript 是 javascript 的類型超集,旨在簡化大型 JavaScript 應用程序的開發。Typescript 加入了常見的概念例如 類(classes),泛型(generics),介面(interfaces)和靜態類型(static types)並允許開發人員使用靜態檢查和代碼重構等工具。

為什麼在意 Typescript

現在問題仍然是為什麼你應該優選使用 Typescript。這有一些關於為什麼 javascript 開發者應該考慮學習 Typescript 的原因。

靜態類型

Javascript 是動態類型的,這意味著直到在運行時實例化時,它不知道變數的類型,這可能導致項目中的問題和錯誤。Typescript 加入了對 Javascript 靜態類型支持如果你正確的使用它處理由變數類型的錯誤設定引起的錯誤。您仍然可以完全控制輸入代碼的嚴格程度,或者甚至根本不使用類型。

更好的 IDE 支持

Typescript 相比 Javascript 一個更大的優勢是更好的 IED 支持包括了來自 Typescript 編譯器智能,實時的提示,調試以及更多功能。這里還有一大堆擴展進一步 提升你的 Typescript 開發體驗。

應用新的 ECMAScript 特性

Typescript 使您可以使用最新的 ECMAScript 功能,並將它們轉換到您選擇的 ECMAScript 目標。這意味著您可以使用最新的工具開發應用程序,而無需擔心瀏覽器支持。

什麼時候你該使用它

到目前為止,我們應該知道為什麼 Typescript 是有用的以及如何改善我們的開發體驗。但它並不是解決所有問題的方法,當然也不能阻止你自己編寫可怕的代碼。那麼讓我們來看看你應該在哪裡使用 Typescript。

當你擁有一個很大的代碼庫時

Typescript 是大型代碼庫的一個很好的補充,因為它可以幫助您防止許多常見錯誤。這尤其適用於多個開發人員工作在同一項目之中。

當你項目成員早已知道靜態類型語言時

另一個明顯使用 Typescript 的場景是當你和你的團隊已經知道靜態類型的語言像 Java 和 C# 不想改為編寫 Javascript。

設置/建立

要設置 typescript,我們只需要使用 npm 包管理器安裝它並創建一個新的 Typescript 文件。

安裝完成之後我們可以繼續探尋 Typescript 提供給我們的語法和功能特性。

類型

現在讓我們來看看 Typescript 所提供的類型:

數值(Number)

Typescript 所有的值類型都是浮點數。所有的數字包括二進制和十六進制都是數值類型。

字元串(String)

與其他語言一樣,Typescript 使用 String 數據類型來保存文本數據。

你還可以用反引號來應用多行字元串並嵌入表達式。

布爾類型(Boolean)

Typescript 支持所有的基本數據類型,布爾類型,值必須為 true 或者 false。

指定類型

現在我們已經有了基本的數據類型,我們可以看看你如何在 Typescript 中指定類型。基本上,您只需要在名稱和冒號後面寫出變數的類型。

單一類型

這里例子為我們如何為變數指定字元串數據類型

所有其他數據類型也是這樣使用。

多類型

你仍然可以通過 | 操作符為你的變數指定多個數據類型:

這里我們使用|為變數分配兩種類型。現在我們可以在其中存儲字元串和數值。

類型檢測

現在讓我們看看我們如何檢查我們的變數是否具有正確的類型。我們有多種選擇,但在這里我只展示了兩個最常用的選項。

Typeof

typeof 僅僅知道基本類型。這意味著它只能檢查變數是否是我們上面定義的數據類型之一。

在此示例中,我們創建一個字元串類型變數並使用 typeof 命令檢查 str 是否為 Number 類型(始終為 false)。然後我們列印是否是數值。

Instanceof

instanceof 運算符與 typeof 幾乎相同,只是它還可以檢查 javascript 尚未定義的自定義類型。

在這里,我們創建一個自定義類型,我們稍後將在本文中討論,然後創建它的實例。之後,我們檢查它是否真的是 Human 類型的變數,如果是,則在控制台中列印。

類型斷言

有時我們還需要將變數轉換為特定的數據類型。這經常發生在你已經指定了一個泛型類型像 any 並且你想使用它具體的類型的方法。

有很多選擇可以解決這個問題,但在這里我只分享其中兩個。

As 關鍵字

通過在變數名之後使用 as 關鍵字跟隨具體的數據類型來轉換變數的類型。

這里我們將 str 變數轉換為字元串,以便我們可以使用 length 屬性(如果您的 TSLINT 設置允許,甚至可以在沒有轉換的情況下工作)。

> 操作符

我們也可以使用 > 運算符,它與 as 關鍵字具有完全相同的效果,只有語法差異。

此代碼塊與上面的代碼塊具有完全相同的功能。它只是語法不同。

數組

Typescript 中的數組是相同對象的集合,可以用兩種不同的方式創建。

創建數組

使用 []

我們可以通過指定類型後跟 [] 來定義數組對象,以表示它是一個數組。

在這個例子中,我們創建一個字元串數組,它包含三個不同的字元串值。

使用泛型數組

我們還可用指定 Array 定義泛型數組

這里我們創建一個數值數組,它包含 5 個不同的數字。

多(混合)類型數組

此外,我們還可以使用 | 操作符將多個類型分配給單個數組。

此例中我們創建了一個數值可以包含字元串和數值。

多維數組

Typescript 還允許我們定義多維數組,這意味著我們可以將數組保存在另一個數組中。我們可以通過使用多個[]運算符來創建一個多維數組。

這里我們創建一個包含另一個數字數組的數組。

元組(Tupels)

元組基本類似數組但有一點不同。我們可以定義每個位子上儲存數據的類型。這意味著我們可以通過方括弧內的枚舉來限制固定索引位置的類型。

在此列中,我們定義了一個簡單的元組,在索引 0 位置上指定為數值類型,在索引為 1 位置上指定為字元串類型。這意味著如果我們嘗試在此索引上放置另一種數據類型,則會拋出錯誤。

以下是非法元組的示例:

枚舉(Enums)

與大多數其他面向對象編程語言一樣,Typescript 中的枚舉允許我們定義一組命名常量。 Typescript 還提供基於數值和基於字元串的枚舉。使用 enum 關鍵字定義 Typescript 中的枚舉。

數值枚舉

首先,我們將查看數值枚舉,其中我們將鍵值與索引匹配。

上面,我們定義了數值枚舉將 Playing 初始化為 0,Paused 為 1 等等。

我們也可以將初始化器留空,而 Typescript 會從零開始自動索引它。

字元串枚舉

定義字元串枚舉也十分簡單,我們只需要在定義的每個枚舉值後初始化字元串值。

這里我們通過使用字元串初始化我們的狀態來定義字元串枚舉。

對象(Objects)

Typescript 中的對象是包含一組鍵值對的實例。這些值可以是變數,數組甚至函數。它也被視為表示非基本類型的數據類型。

我們可以使用大括弧創建一個對象:

這里我們創建了一個 human 對象包含三個不同的鍵值對。

我們可以為對象加入方法:

自定義類型

Typescript 還允許我們自定義類型,以便於我們後續重用。要創建自定義類型,我們只需要使用 type 關鍵字並定義我們的類型。

在此示例中,我們定義了一個名為 Human 包含三個屬性的自定義類型。現在讓我們看看如何創建這種類型的對象。

在這里,我們創建自定義類型的實例並設置所需的屬性。

方法參數和返回類型

Typescript 允許我們為方法參數和返回值指定數據類型。現在讓我們看一下使用 Typescript 定義函數的語法。

這里我們有兩個示例函數,它們都具有定義類型的參數。我們還看到在結束括弧後定義返回類型。

現在我們可以像普通的 javascript 一樣調用我們的函數,但編譯器會檢查我們是否為函數提供了正確的參數。

可選屬性

Typescript 允許我們為方法(註:介面等同樣可以定義可選屬性)定義可選屬性。我們通過 ? 操作符定義。

在這個例子中,lastName 是一個可選參數,這意味著當我們不提供調用函數時,我們不會從編譯器中獲得錯誤。

這表示 2 個示例都被視為正確的。

默認值

我們使用可選屬性的第二種方法是為它指定一個默認值。我們可以通過直接在函數頭部賦值來實現。

在此例我中我們 lastName 賦予了默認值這意味著我們不必每次調用方法時提供它。

介面(Interfaces)

讓我們看個例子讓定義更加清晰:

可選屬性

在 Typescript 中,有時並不是所有介面屬性都是必需的。可以使用 ? 運算符在屬性後面將其設置為可選。

在這里,我們創建一個具有一個普通和一個可選屬性的介面,該屬性是使用 ? 運算符。這就是我們兩個人初始化都有效的原因。

只讀屬性

我們的介面中一些屬性也應該只在首次創建對象時修改賦值。我們可以通過將 readonly 關鍵字放在我們的屬性名稱之前來指定此功能。

在此示例中,id 屬性是只讀的,在創建對象後無法更改。

模塊(Barrels Moles)

Barrels 允許我們在一個更方便的模塊中匯總多個導出模塊。

我們僅需要創建一個新文件,它將導出我們項目中的多個模塊 (譯者註:根據 ECMAScript 定義一個文件定義一個模塊,此處可能表示模塊聚合(類似庫等的入口文件))。

之後我們可以通過這個便利的單一導入語句引入這些模塊。

泛型(Generics)

泛型允許我們創建兼容廣泛類型而不是單一類型的組件。這使得我們的組件「 開放」和復用。

現在您可能想知道為什麼我們不只是使用任何( any )類型來使組件接受多種類型而不是單一類型。讓我們看一個例子更好地了解。

我們想要一個簡單的假函數(mmy function),它返回傳入的參數:

然而 any 是通用的,某種程度它能接受所有類型參數但有一個很大的區別。我們丟失了我們傳入的參數是什麼類型以及返回值是什麼類型。

所以讓我們來看看,我們如何接受所有類型並知道它返回值的類型。

這里我們使用泛型參數 T,因此我們可以捕獲變數類型並在以後使用它。我們還使用它作為返回參數類型,它允許我們在檢查代碼時看到相應的類型。

更多詳細介紹你可以查看Charly Poly關於Generics and overloads的文章

訪問修飾符(Access Modifiers)

訪問修飾符控制我們類成員的可訪問性。 Typescript 支持三種訪問修飾符 - 公共的(public),私有的(private)和受保護的(protected)。

公共的

公共成員可以在任何地方訪問,沒有任何限制 這也是標准修飾符,這意味著您不需要使用 public 關鍵字為變數添加前綴。

私有的

私有成員只能在其定義的類中能訪問。

受保護的

保護成員只能在其定義的類及其子類中訪問。

TSLINT

TSLINT 是 Typescript 的標准 linter,可以幫助我們編寫干凈,可維護和可讀的代碼。它可以使用我們自己的 lint 規則,配置和格式化程序進行自定義。

設置

首先我們需要安裝 Typescript 和 tslint,我們可以全局安裝和局部安裝:

之後,我們可以使用 TSLINT CLI 在我們的項目中初始化 TSLINT。

現在我們有了 tslint.json 文件,我們可以開始配置我們的規則了。

配置

TSLINT 允許使用配置我們自己的規則並自定義代碼的外觀。默認情況下,tslint.json 文件看起來像這樣,只使用默認規則。

我們可以通過將它們放在 rules 對象中來添加其他規則。

有關所有可用規則的 概述,您可以查看官方文檔。

結論

恭喜您一路走到最後!希望此篇文章幫助您理解 Typescript 的基礎知識以及如何在項目中使用。

如果您發現這個有用,請考慮推薦並與其他開發人員共享。也可以訪問我的網站學習更多。https://www.icoderoad.com

如果您有任何問題和反饋,在以下評論中讓我知道。

Ⅵ TypeScript 入門指南

新系列 深入淺出TypeScript 來了,本系列至少20+篇。本文為第一篇,來介紹一下TypeScript 以及常見的類型。

TypeScript是一門由微軟推出的開源的、跨平台的編程語言。它是JavaScript的超集,擴展了 JavaScript 的語法,最終會被編譯為JavaScript代碼。

TypeScript的主要特性:

TypeScript 主要是為了實現以下兩個目標:

下面就來看看這兩個目標是如何實現的。

為什麼要給JavaScript加上類型呢?

我們知道,JavaScript是一種輕量級的解釋性腳本語言。也是弱類型、動態類型語言,允許隱式轉換,只有運行時才能確定變數的類型。正是因為在運行時才能確定變數的類型,JavaScript代碼很多錯誤在運行時才能發現。TypeScript在JavaScript的基礎上,包裝了類型機制,使其變身成為 靜態類型 語言。在 TypeScript 中,不僅可以輕易復用 JavaScript 的代碼、最新特性,還能使用可選的靜態類型進行檢查報錯,使得編寫的代碼更健壯、更易於維護。

下面是 JavaScript 項目中最常見的十大錯誤,如果使用 TypeScript,那麼在 編寫階段 就可以發現並解決很多 JavaScript 錯誤了:

類型系統能夠提高代碼的質量和可維護性,經過不斷的實踐,以下兩點尤其需要注意:

可以認為,在所有操作符之前,TypeScript 都能檢測到接收的類型(在代碼運行時,操作符接收的是實際數據;在靜態檢測時,操作符接收的則是類型)是否被當前操作符所支持。當 TypeScript 類型檢測能力覆蓋到所有代碼後,任意破壞約定的改動都能被自動檢測出來,並提出類型錯誤。因此,可以放心地修改、重構業務邏輯,而不用擔憂因為考慮不周而犯下低級錯誤。

在一些語言中,類型總是有一些不必要的復雜的存在方式,而 TypeScript 盡可能地降低了使用門檻,它是通過如下方式來實現的。

TypeScript 與 JavaScript 本質並無區別,我們可以將 TypeScipt 理解為是一個添加了類型註解的 JavaScript,為JavaScript代碼提供了編譯時的類型安全。

實際上,TypeScript 是一門「 中間語言 」,因為它最終會轉化為JavaScript,再交給瀏覽器解釋、執行。不過 TypeScript 並不會破壞 JavaScript 原有的體系,只是在 JavaScript 的基礎上進行了擴展。

准確的說,TypeScript 只是將JavaScript中的方法進行了標准化處理:

這段代碼在TypeScript中就會報錯,因為TS會知道a是一個數字類型,不能將其他類型的值賦值給a,這種類型的推斷是很有必要的。

上面說了,TypeScript會盡可能安全的推斷類型。我們也可以使用類型注釋,以實現以下兩件事:

在一些語言中,類型總是有一些不必要的復雜的存在方式,而 TypeScript 的類型是結構化的。比如下面的例子中,函數會接受它所期望的參數:

為了便於把 JavaScript 代碼遷移至 TypeScript,即使存在編譯錯誤,在默認的情況下,TypeScript 也會盡可能的被編譯為 JavaScript 代碼。因此,我們可以將JavaScript代碼逐步遷移至 TypeScript。

雖然 TypeScript 是 JavaScript 的超集,但它始終緊跟ECMAScript標准,所以是支持ES6/7/8/9 等新語法標準的。並且,在語法層面上對一些語法進行了擴展。TypeScript 團隊也正在積極的添加新功能的支持,這些功能會隨著時間的推移而越來越多,越來越全面。

雖然 TypeScript 比較嚴謹,但是它並沒有讓 JavaScript 失去其靈活性。TypeScript 由於兼容 JavaScript 所以靈活度可以媲美 JavaScript,比如可以在任何地方將類型定義為 any(當然,並不推薦這樣使用),畢竟 TypeScript 對類型的檢查嚴格程度是可以通過 tsconfig.json 來配置的。

在搭建TypeScript環境之前,先來看看適合TypeScript的IDE,這里主要介紹Visual Studio Code,筆者就一直使用這款編輯器。

VS Code可以說是微軟的親兒子了,其具有以下優勢:

因為 VS Code 中內置了特定版本的 TypeScript 語言服務,所以它天然支持 TypeScript 語法解析和類型檢測,且這個內置的服務與手動安裝的 TypeScript 完全隔離。因此, VS Code 支持在內置和手動安裝版本之間動態切換語言服務,從而實現對不同版本的 TypeScript 的支持。

如果當前應用目錄中安裝了與內置服務不同版本的 TypeScript,我們就可以點擊 VS Code 底部工具欄的版本號信息,從而實現 「use VS Code's Version」 和 「use Workspace's Version」 兩者之間的隨意切換。

除此之外,VS Code 也基於 TypeScript 語言服務提供了准確的代碼自動補全功能,並顯示詳細的類型定義信息,大大的提升了我們的開發效率。

1)全局安裝TypeScript:

2)初始化配置文件:

執行之後,項目根目錄會出現一個 tsconfig.json 文件,裡麵包含ts的配置項(可能因為版本不同而配置略有不同)。

可以在 package.json 中加入script命令:

3)編譯ts代碼:

TSLint 是一個通過 tslint.json 進行配置的插件,在編寫TypeScript代碼時,可以對代碼風格進行檢查和提示。如果對代碼風格有要求,就需要用到TSLint了。其使用步驟如下: (1)在全局安裝TSLint:

(2)使用TSLint初始化配置文件:

執行之後,項目根目錄下多了一個 tslint.json 文件,這就是TSLint的配置文件了,它會根據這個文件對代碼進行檢查,生成的 tslint.json 文件有下面幾個欄位:

這些欄位的含義如下;

在說TypeScript數據類型之前,先來看看在TypeScript中定義數據類型的基本語法。

在語法層面,預設類型註解的 TypeScript 與 JavaScript 完全一致。因此,可以把 TypeScript 代碼的編寫看作是為 JavaScript 代碼添加類型註解。

在 TypeScript 語法中,類型的標注主要通過類型後置語法來實現:「 變數: 類型

在 JavaScript 中,原始類型指的是 非對象且沒有方法 的數據類型,包括:number、boolean、string、null、undefined、symbol、bigInt。

它們對應的 TypeScript 類型如下:

JavaScript原始基礎類型TypeScript類型 numbernumber booleanboolean stringstring nullnull undefinendefined symbolsymbol bigIntbigInt

需要注意 number Number 的區別:TypeScript中指定類型的時候要用 number ,這是TypeScript的類型關鍵字。而 Number 是 JavaScript 的原生構造函數,用它來創建數值類型的值,這兩個是不一樣的。包括 string boolean 等都是TypeScript的類型關鍵字,而不是JavaScript語法。

TypeScript 和 JavaScript 一樣,所有數字都是 浮點數 ,所以只有一個 number 類型。

TypeScript 還支持 ES6 中新增的二進制和八進制字面量,所以 TypeScript 中共支持 2、8、10和16 這四種進制的數值:

字元串類型可以使用單引號和雙引號來包裹內容,但是如果使用 Tslint 規則,會對引號進行檢測,使用單引號還是雙引號可以在 Tslint 規則中進行配置。除此之外,還可以使用 ES6 中的模板字元串來拼接變數和字元串會更為方便。

類型為布爾值類型的變數的值只能是true或者false。除此之外,賦值給布爾值的值也可以是一個計算之後結果為布爾值的表達式:

在 JavaScript 中,undefined和 null 是兩個基本數據類型。在 TypeScript 中,這兩者都有各自的類型,即 undefined 和 null,也就是說它們既是實際的值,也是類型。這兩種類型的實際用處不是很大。

注意,第一行代碼可能會報一個tslint的錯誤: Unnecessary initialization to 'undefined' ,就是不能給一個變數賦值為undefined。但實際上給變數賦值為undefined是完全可以的,所以如果想讓代碼合理化,可以配置tslint,將" no-unnecessary-initializer "設置為 false 即可。

默認情況下,undefined 和 null 是所有類型的子類型,可以賦值給任意類型的值,也就是說可以把 undefined 賦值給 void 類型,也可以賦值給 number 類型。當在 tsconfig.json 的"compilerOptions"里設置為 "strictNullChecks": true 時,就必須嚴格對待了。這時 undefined 和 null 將只能賦值給它們自身或者 void 類型。這樣也可以規避一些錯誤。

BigInt是ES6中新引入的數據類型,它是一種內置對象,它提供了一種方法來表示大於 2- 1 的整數,BigInt可以表示任意大的整數。

使用 BigInt 可以安全地存儲和操作大整數,即使這個數已經超出了JavaScript構造函數 Number 能夠表示的安全整數范圍。

我們知道,在 JavaScript 中採用雙精度浮點數,這導致精度有限,比如 Number.MAX_SAFE_INTEGER 給出了可以安全遞增的最大可能整數,即 2- 1 ,來看一個例子:

可以看到,最終返回了true,這就是超過精讀范圍造成的問題,而 BigInt 正是解決這類問題而生的:

這里需要用 BigInt(number) 把 Number 轉化為 BigInt ,同時如果類型是 BigInt ,那麼數字後面需要加 n 。

在TypeScript中, number 類型雖然和 BigInt 都表示數字,但是實際上兩者類型是完全不同的:

symbol我們平時用的比較少,所以可能了解也不是很多,這里就詳細來說說symbol。

symbol 是 ES6 新增的一種基本數據類型,它用來表示獨一無二的值,可以通過 Symbol 構造函數生成。

注意:Symbol 前面不能加 new關鍵字,直接調用即可創建一個獨一無二的 symbol 類型的值。

可以在使用 Symbol 方法創建 symbol 類型值的時候傳入一個參數,這個參數需要是一個字元串。如果傳入的參數不是字元串,會先自動調用傳入參數的 toString 方法轉為字元串:

上面代碼的第三行可能會報一個錯誤:This condition will always return 'false' since the types 'unique symbol' and 'unique symbol' have no overlap. 這是因為編譯器檢測到這里的 s1 === s2 始終是false,所以編譯器提醒這代碼寫的多餘,建議進行優化。

上面使用Symbol創建了兩個symbol對象,方法中都傳入了相同的字元串,但是兩個symbol值仍然是false,這就說明了 Symbol 方法會返回一個獨一無二的值。Symbol 方法傳入的這個字元串,就是方便我們區分 symbol 值的。可以調用 symbol 值的 toString 方法將它轉為字元串:

在TypeScript中使用symbol就是指定一個值的類型為symbol類型:

在ES6中,對象的屬性是支持表達式的,可以使用於一個變數來作為屬性名,這對於代碼的簡化有很多用處,表達式必須放在大括弧內:

symbol 也可以作為屬性名,因為symbol的值是獨一無二的,所以當它作為屬性名時,不會與其他任何屬性名重復。當需要訪問這個屬性時,只能使用這個symbol值來訪問(必須使用方括弧形式來訪問):

在使用obj.name訪問時,實際上是字元串name,這和訪問普通字元串類型的屬性名是一樣的,要想訪問屬性名為symbol類型的屬性時,必須使用方括弧。方括弧中的name才是我們定義的symbol類型的變數name。

使用 Symbol 類型值作為屬性名,這個屬性是不會被 for…in遍歷到的,也不會被 Object.keys() 、 Object.getOwnPropertyNames() 、 JSON.stringify() 等方法獲取到:

雖然這些方法都不能訪問到Symbol類型的屬性名,但是Symbol類型的屬性並不是私有屬性,可以使用 Object.getOwnPropertySymbols 方法獲取對象的所有symbol類型的屬性名:

除了這個方法,還可以使用ES6提供的 Reflect 對象的靜態方法 Reflect.ownKeys ,它可以返回所有類型的屬性名,Symbol 類型的也會返回:

Symbol 包含兩個靜態方法, for 和 keyFor 。 1)Symbol.for()

用Symbol創建的symbol類型的值都是獨一無二的。使用 Symbol.for 方法傳入字元串,會先檢查有沒有使用該字元串調用 Symbol.for 方法創建的 symbol 值。如果有,返回該值;如果沒有,則使用該字元串新創建一個。使用該方法創建 symbol 值後會在全局范圍進行注冊。

上面代碼中,創建了一個iframe節點並把它放在body中,通過這個 iframe 對象的 contentWindow 拿到這個 iframe 的 window 對象,在 iframe.contentWindow上添加一個值就相當於在當前頁面定義一個全局變數一樣。可以看到,在 iframe 中定義的鍵為 TypeScript 的 symbol 值在和在當前頁面定義的鍵為'TypeScript'的symbol 值相等,說明它們是同一個值。

2)Symbol.keyFor() 該方法傳入一個 symbol 值,返回該值在全局注冊的鍵名:

看完簡單的數據類型,下面就來看看比較復雜的數據類型,包括JavaScript中的數組和對象,以及TypeScript中新增的元組、枚舉、Any、void、never、unknown。

在 TypeScript 中有兩種定義數組的方式:

以上兩種定義數組類型的方式雖然本質上沒有任何區別,但是更推薦使用第一種形式來定義。一方面可以避免與 JSX 語法沖突,另一方面可以減少代碼量。

注意,這兩種寫法中的 number 指定的是數組元素的類型,也可以在這里將數組的元素指定為其他任意類型。如果要指定一個數組里的元素既可以是數值也可以是字元串,那麼可以使用這種方式: number|string[] 。

在JavaScript中,object是引用類型,它存儲的是值的引用。在TypeScript中,當想讓一個變數或者函數的參數的類型是一個對象的形式時,可以使用這個類型:

可以看到,當給一個對象類型的變數賦值一個對象時,就會報錯。對象類型更適合以下場景:

在 JavaScript 中並沒有元組的概念,作為一門動態類型語言,它的優勢是支持多類型元素數組。但是出於較好的擴展性、可讀性和穩定性考慮,我們通常會把不同類型的值通過鍵值對的形式塞到一個對象中,再返回這個對象,而不是使用沒有任何限制的數組。TypeScript 的元組類型正好彌補了這個不足,使得定義包含固定個數元素、每個元素類型未必相同的數組成為可能。

元組可以看做是數組的擴展,它表示已知元素數量和類型的數組,它特別適合用來實現多值返回。確切的說,就是已知數組中每一個位置上的元素的類型,可以通過元組的索引為元素賦值::

可以看到,定義的arr元組中,元素個數和元素類型都是確定的,當為arr賦值時,各個位置上的元素類型都要對應,元素個數也要一致。

當訪問元組元素時,TypeScript也會對元素做類型檢查,如果元素是一個字元串,那麼它只能使用字元串方法,如果使用別的類型的方法,就會報錯。

在TypeScript 新的版本中,TypeScript會對元組做越界判斷。超出規定個數的元素稱作越界元素,元素賦值必須類型和個數都對應,不能超出定義的元素個數。

這里定義了介面 Tuple ,它繼承數組類型,並且數組元素的類型是 number 和 string 構成的聯合類型,這樣介面 Tuple 就擁有了數組類型所有的特性。並且指定索引為0的值為 string 類型,索引為1的值為 number 類型,同時指定 length 屬性的類型字面量為 2,這樣在指定一個類型為這個介面 Tuple 時,這個值必須是數組,而且如果元素個數超過2個時,它的length就不是2是大於2的數了,就不滿足這個介面定義了,所以就會報錯;當然,如果元素個數不夠2個也會報錯,因為索引為0或1的值缺失。

TypeScript 在 ES 原有類型基礎上加入枚舉類型,使得在 TypeScript 中也可以給一組數值賦予名字,這樣對開發者比較友好。枚舉類型使用enum來定義:

上面定義的枚舉類型的Roles,它有三個值,TypeScript會為它們每個值分配編號,默認從0開始,在使用時,就可以使用名字而不需要記數字和名稱的對應關系了:

除此之外,還可以修改這個數值,讓SUPER_ADMIN = 1,這樣後面的值就分別是2和3。當然還可以給每個值賦予不同的、不按順序排列的值:

我們可以將一個值定義為any類型,也可以在定義數組類型時使用any來指定數組中的元素類型為任意類型:

any 類型會在對象的調用鏈中進行傳導,即any 類型對象的任意屬性的類型都是 any,如下代碼所示:

需要注意:不要濫用any類型,如果代碼中充滿了any,那TypeScript和JavaScript就毫無區別了,所以除非有充足的理由,否則應該盡量避免使用 any ,並且開啟禁用隱式 any 的設置。

void 和 any 相反,any 是表示任意類型,而 void 是表示沒有類型,就是什麼類型都不是。這在 定義函數,並且函數沒有返回值時會用到

需要注意: void 類型的變數只能賦值為 undefined 和 null ,其他類型不能賦值給 void 類型的變數。

never 類型指永遠不存在值的類型,它是那些 總會拋出異常 根本不會有返回值的函數表達式的返回值 類型,當變數被永不為真的類型保護所約束時,該變數也是 never 類型。

下面的函數,總是會拋出異常,所以它的返回值類型是never,用來表明它的返回值是不存在的:

never 類型是任何類型的子類型,所以它可以賦值給任何類型;而沒有類型是 never 的子類型,所以除了它自身以外,其他類型(包括 any 類型)都不能為 never 類型賦值。

上面代碼定義了一個立即執行函數,函數體是一個死循環,這個函數調用後的返回值類型為 never,所以賦值之後 neverVariable 的類型是 never 類型,當給neverVariable 賦值 123 時,就會報錯,因為除它自身外任何類型都不能賦值給 never 類型。

基於 never 的特性,我們可以把 never 作為介面類型下的屬性類型,用來禁止操作介面下特定的屬性:

可以看到,無論給 props.name 賦什麼類型的值,它都會提示類型錯誤,這就相當於將 name 屬性設置為了只讀 。

unknown 是TypeScript在3.0版本新增的類型,主要用來描述類型並不確定的變數。它看起來和any很像,但是還是有區別的,unknown相對於any更安全。

對於any,來看一個例子:

上面這些語句都不會報錯,因為value是any類型,所以後面三個操作都有合法的情況,當value是一個對象時,訪問name屬性是沒問題的;當value是數值類型的時候,調用它的toFixed方法沒問題;當value是字元串或數組時獲取它的length屬性是沒問題的。

當指定值為unknown類型的時候,如果沒有 縮小類型範圍 的話,是不能對它進行任何操作的。總之,unknown類型的值不能隨便操作。那什麼是類型範圍縮小呢?下面來看一個例子:

這里由於把value的類型縮小為Date實例的范圍內,所以進行了value.toISOString(),也就是使用ISO標准將 Date 對象轉換為字元串。

使用以下方式也可以縮小類型範圍:

關於 unknown 類型,在使用時需要注意以下幾點:

在實際使用中,如果有類型無法確定的情況,要盡量避免使用 any,因為 any 會丟失類型信息,一旦一個類型被指定為 any,那麼在它上面進行任何操作都是合法的,所以會有意想不到的情況發生。因此如果遇到無法確定類型的情況,要先考慮使用 unknown。

Ⅶ typescript教程是什麼

沒有掛網公布

TypeScript是微軟開發的一個開源的編程語言,通過在JavaScript的基礎上添加靜態類型定義構建而成。TypeScript通過TypeScript編譯器或Babel轉譯為JavaScript代碼,可運行在任何瀏覽器,任何操作系統。

TypeScript添加了很多尚未正式發布的ECMAScript新特性(如裝飾器)。2012年10月,微軟發布了首個公開版本的TypeScript,2013年6月19日,在經歷了一個預覽版之後微軟正式發布了正式版TypeScript。當前最新版本為TypeScript 4.0。

Ⅷ 來做操吧!深入 TypeScript 高級類型和類型體操

TypeScript 給 JavaScript 擴展了類型的語法,我們可以給變數加上類型,在編譯期間會做類型檢查,配合編輯器還能做更准確的智能提示。此外,TypeScript 還支持了高級類型用於增加類型系統的靈活性。

就像 JavaScript 的高階函數是生成函數的函數,React 的高階組件是生成組件的組件一樣,Typescript 的高級類型就是生成類型的類型。

TypeScript 高級類型是通過 type 定義的有類型參數(也叫泛型)的類型,它會對傳入的類型參數做一系列的類型計算,產生新的類型。

type Pick = {

[P in K]: T[P];

};

比如,這個 Pick 就是一個高級類型,它有類型參數 T 和 K,類型參數經過一系列的類型計算邏輯,會返回新的類型。

TypeScript 高級類型會根據類型參數求出新的類型,這個過程會涉及一系列的類型計算邏輯,這些類型計算邏輯就叫做類型體操。當然,這並不是一個正式的概念,只是社區的戲稱,因為有的類型計算邏輯是比較復雜的。

TypeScript 的類型系統是圖靈完備的,也就是說它能描述任何可計算邏輯,簡單點來說就是循環、條件判斷等該有的語法都有。

既然 TypeScript 的類型系統這么強,那我們就做一些高級類型的類型體操來感受下吧。

我們會做這些體操:

用 ts 類型實現加法

用 ts 類型生成重復 N 次的字元串

用 ts 類型實現簡易的 js parser(部分)

用 ts 類型實現對象屬性按條件過濾

我把這些體操分為數字類的、字元串類的、對象類的,把這三種類型計算邏輯的規律掌握了,相信你的體操水平會提升一截。

TypeScript 類型語法基礎

在做體操之前,要先過一下 TypeScript 的類型語法,也就是能做哪些類型計算邏輯。

既然說該有的語法都有,那我們來看下循環和判斷都怎麼做:

ts 類型的條件判斷

圖片

ts 類型的條件判斷的語法是 條件 ? 分支1 : 分支2 。

extends 關鍵字是用於判斷 A 是否是 B 類型的。例子中傳入的類型參數 T 是 1,是 number 類型,所以最終返回的是 true。

ts 類型的循環

圖片ts 類型沒有循環,但可以用遞歸來實現循環。

我們要構造一個長度為 n 的數組,那麼就要傳入長度的類型參數 Len、元素的類型參數 Ele、以及構造出的數組的類型參數 Arr(用於遞歸)。

然後類型計算邏輯就是判斷 Arr 的 length 是否是 Len,如果是的話,就返回構造出的 Arr,不是的話就往其中添加一個元素繼續構造。

這樣,我們就遞歸的創建了一個長度為 Len 的數組。

ts 類型的字元串操作

ts 支持構造新的字元串:

圖片

也支持根據模式匹配來取字元串中的某一部分:

圖片

ts 類型的對象操作

ts 支持對對象取屬性、取值:

圖片

也可以創建新的對象類型:

圖片

通過 keyof 取出 obj 的所有屬性名,通過 in 遍歷屬性名並取對應的屬性值,通過這些來生成新的對象類型 newObj。

我們過了一下常用的 ts 類型的語法,包括條件判斷、循環(用遞歸實現)、字元串操作(構造字元串、取某部分子串)、對象操作(構造對象、取屬性值)。接下來就用這些來做操吧。

ts 類型體操練習

我們把體操分為 3 類來練習,之後再分別總結規律。

數字類的類型體操

體操 1:實現高級類型 Add,能夠做數字加法。

ts 類型能做數字加法么?肯定可以的,因為它是圖靈完備的,也就是各種可計算邏輯都可以做。

那怎麼做呢?

數組類型可以取 length 屬性,那不就是個數字么。可以通過構造一定長度的數組來實現加法。

上文我們實現了通過遞歸的方式實現了構造一定長度的新數組的高級類型:

type createArray = Arr['length'] extends Len ? Arr : createArray

那隻要分別構造兩個不同長度的數組,然後合並到一起,再取 length 就行了。

type Add = [...createArray, ...createArray ]['length']

我們測試下:

圖片

我們通過構造數組的方式實現了加法!

小結下:ts 的高級類型想做數字的運算只能用構造不同長度的數組再取 length 的方式,因為沒有類型的加減乘除運算符。

字元串類的體操

體操2:把字元串重復 n 次。

字元串的構造我們前面學過了,就是通過 ${A}${B} 的方式,那隻要做下計數,判斷下重復次數就行了。

計數涉及到了數字運算,要通過構造數組再取 length 的方式。

所以,我們要遞歸的構造數組來計數,並且遞歸的構造字元串,然後判斷數組長度達到目標就返回構造的字元串。

所以有 Str(待重復的字元串)、Count(重復次數)、Arr(用於計數的數組)、ResStr(構造出的字元串)四個類型參數:

type RepeactStr<str p="" string,

Count,

Arr extends Str[] = [],

ResStr extends string = ''>

= Arr['length'] extends Count

? ResStr

: RepeactStr ;

我們遞歸的構造了數組和字元串,判斷構造的數組的 length 如果到了 Count,就返回構造的字元串 ResStr,否則繼續遞歸構造。

測試一下:

圖片

小結:遞歸構造字元串的時候要通過遞歸構造數組來做計數,直到計數滿足條件,就生成了目標的字元串。

這個體操只用到了構造字元串,沒用到字元串通過模式匹配取子串,我們再做一個體操。

體操3: 實現簡易的 JS Parser,能解析字元串 add(11,22) 的函數名和參數

字元串的解析需要根據模式匹配取子串。這里要分別解析函數名(functionName)、括弧(brackets)、數字(num)、逗號(comma),我們分別實現相應的高級類型。

解析函數名

函數名是由字母構成,我們只要一個個字元一個字元的取,判斷是否為字母,是的話就記錄下該字元,然後對剩下的字元串遞歸進行同樣的處理,直到不為字母的字元,通過這樣的方式就能取出函數名。

我們先定義字母的類型:

type alphaChars = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm'

| 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'

| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M'

| 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';

還有保存中間結果的類型:

type TempParseResult = {

token: Token,

rest: Rest

}

然後就一個個取字元來判斷,把取到的字元構造成字元串存入中間結果:

type parseFunctionName

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends alphaChars

? parseFunctionName

: TempParseResult

: never;

我們取了單個字元,然後判斷是否是字母,是的話就把取到的字元構造成新的字元串,然後繼續遞歸取剩餘的字元串。

測試一下:

圖片

圖片

符合我們的需求,我們通過模式匹配取子串的方式解析出了函數名。

然後繼續解析剩下的。

解析括弧

括弧的匹配也是同樣的方式,而且括弧只有一個字元,不需要遞歸的取,取一次就行。

type brackets = '(' | ')';

type parseBrackets

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends brackets

? TempParseResult

: never

: never;

測試一下:

圖片

繼續解析剩下的:

解析數字

數字的解析也是一個字元一個字元的取,判斷是否匹配,匹配的話就遞歸取下一個字元,直到不匹配:

type numChars = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';

type parseNum

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends numChars

? parseNum

: TempParseResult

: never;

測試一下:

圖片

繼續解析剩下的:

解析逗號

逗號和括弧一樣,只需要取一個字元判斷即可,不需要遞歸。

type parseComma

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends ','

? TempParseResult

: never

: never;

測試一下:

圖片

至此,我們完成了所有的字元的解析,解析來按照順序組織起來就行。

整體解析

單個 token 的解析都做完了,整體解析就是組織下順序,每次解析完拿到剩餘的字元串傳入下一個解析邏輯,全部解析完,就可以拿到各種信息。

type parse

= parseFunctionName extends TempParseResult

? parseBrackets extends TempParseResult

? parseNum extends TempParseResult

? parseComma extends TempParseResult

? parseNum extends TempParseResult

? parseBrackets extends TempParseResult

? {

functionName: FunctionName,

params: [Num1, Num2],

}: never: never: never: never : never : never;

測試一下:

圖片

大功告成,我們用 ts 類型實現了簡易的 parser!

小結:ts 類型可以通過模式匹配的方式取出子串,我們通過一個字元一個字元的取然後判斷的方式,遞歸的拆分 token,然後按照順序拆分出 token,就能實現字元串的解析。

完整代碼如下:

type numChars = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';

type alphaChars = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm'

| 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'

| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M'

| 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';

type TempParseResult = {

token: Token,

rest: Rest

}

type parseFunctionName =

SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends alphaChars

? parseFunctionName

: TempParseResult

: never;

type brackets = '(' | ')';

type parseBrackets

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends brackets

? TempParseResult

: never

: never;

type parseNum

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends numChars

? parseNum

: TempParseResult

: never;

type parseComma

= SourceStr extends `${infer PrefixChar}${infer RestStr}`

? PrefixChar extends ','

? TempParseResult

: never

: never;

type parse

= parseFunctionName extends TempParseResult

? parseBrackets extends TempParseResult

? parseNum extends TempParseResult

? parseComma extends TempParseResult

? parseNum extends TempParseResult

? parseBrackets extends TempParseResult

? {

functionName: FunctionName,

params: [Num1, Num2],

}: never: never: never: never : never : never;

type res = parse;

對象類的體操

體操4:實現高級類型,取出對象類型中的數字屬性值

構造對象、取屬性名、取屬性值的語法上文學過了,這里組合下就行:

type filterNumberProp = {

[Key in keyof T] : T[Key] extends number ? T[Key] : never

}[keyof T];

我們構造一個新的對象類型,通過 keyof 遍歷對象的屬性名,然後對屬性值做判斷,如果不是數字就返回 never,然後再取屬性值。

屬性值返回 never 就代表這個屬性不存在,就能達到過濾的效果。

測試一下:

圖片

小結:對象類型可以通過 {} 構造新對象,通過 [] 取屬性值,通過 keyof 遍歷屬性名,綜合這些語法就可以實現各種對象類型的邏輯。

總結

TypeScript 給 JavaScript 擴展了類型的語法,而且還支持了高級類型來生成類型。

TypeScript 的類型系統是圖靈完備的,可以描述任何可計算邏輯:

有 ? : 可以做條件判斷,常配合 extends 使用

通過遞歸可以實現循環

可以做對象的構造 {}、取屬性名 keyof、取屬性值 T[Key]

可以做字元串的構造 ${a}${b},字元串的模式匹配來取子串 str extends ${infer x}${infer y}

我們分別做了這些類型體操:

ts 實現加法:通過遞歸構造數組再取長度

ts 實現重復字元串:遞歸構造數組來計數,然後遞歸構造字元串

ts 實現 parser:通過字元串模式匹配取子串的方式來解析每一部分,最後組合調用

ts 實現對象屬性過濾:通過構造對象、取屬性名、取值的語法組合調用

其中要注意的就是數字類的要通過構造數組取長度的方式來計算,再就是字元串的模式匹配結合 infer 保存中間結果來取子串,這兩個是相對難度大一些的。

其實各種高級類型,只要熟悉了 ts 類型語法,想清楚了邏輯就能一步步寫出來,和寫 JS 邏輯沒啥本質區別,只不過它是用於生成類型的邏輯。

讀到這里,是不是感覺高級類型的類型體操也沒有啥難度了呢?

Ⅸ 如何評價 TypeScript

現在的Javascript遵循ECMA5的規范,TypeScript是語法上對ECMA6的實現。但現在的TypeScript需要編譯(不是真正的編譯,其實就是語法處理)後轉換成Javascript才能執行。

對於Javascript來說TypeScript就像來自未來的自己。

TypeScript可以做Javascript能做到的所有事,並且還能做Javascript不能做到的事。
比如:
1:搞面向對象巨方便
2:可選的強類型可以讓你在程序運行之前多發現一些錯誤
3:為IDE給javascript彈智能提示打下了良好的基礎

閱讀全文

與typescript編譯混淆相關的資料

熱點內容
圓形相框是什麼app 瀏覽:479
安卓微信如何設置文字加長 瀏覽:764
中科編譯科技公司高新技術企業 瀏覽:770
win7文件夾選項功能 瀏覽:90
微信文件夾為什麼會被鎖定 瀏覽:994
加密系列號 瀏覽:458
電冰箱換壓縮機要注意什麼 瀏覽:795
平板的訪客模式如何加密 瀏覽:139
釘釘加密有用嗎 瀏覽:112
加密u盤好還是不加密的 瀏覽:349
微觀經濟學平狄克第八版pdf 瀏覽:404
linux查看實時流量 瀏覽:557
如何存檔到伺服器 瀏覽:548
flash編程書籍推薦 瀏覽:836
php獲得數組鍵值 瀏覽:402
香港雲伺服器操作 瀏覽:303
wpe最新源碼 瀏覽:857
自己購買雲主伺服器推薦 瀏覽:422
個人所得稅java 瀏覽:761
多餘的伺服器滑道還有什麼用 瀏覽:192