更好的開發(fā)體驗
在開發(fā)中解決 js 解決不了的問題
- 使用不存在的函數(shù)掂摔、變量说莫、成員
- 類型錯誤:把一個不確定的類型杨箭,當作一個確定的類型使用
- 使用 undefined 或者 null 的成員
Uncaught TypeError: Cannot read property xxx of null
, 熟悉嘛? - ...
JavaScript
- 弱類型:變量可以隨時更改類型储狭。
var a;
var a = 10;
var a = 'string';
在聲明變量的時候互婿, 我們就沒有給變量 a 一個確定的類型捣郊,所以在開發(fā)中,a 的類型可以任意改變慈参,而事實上真的需要這樣做嗎(或者說允許一個變量可以隨意更改一個類型真的是好事嗎)呛牲?
var width = 100;
// 省略三千行代碼
width = '200px';
//再省略三千行代碼
document.getElementById('xxx').style.width = ???
我們在投入業(yè)務開發(fā)中的時候, 更多的關注點在于業(yè)務驮配,而不是語言特性娘扩,所以在某個時間節(jié)點,我也不知道width
被重新賦值了多少次壮锻,我現(xiàn)在想用width
這個變量的時候琐旁,width
究竟是個什么?數(shù)字還是字符串猜绣? 要不要加上"px"
, 不回去看代碼九成不知道灰殴。
如果有一個東西,能夠在我第二次將 width
變成一個字符串的時候掰邢, 提醒我牺陶, 你不能這么干, 這個width
原來是一個數(shù)字辣之,你寫成了字符串掰伸,后面會出現(xiàn)混亂!
- 解釋型語言:錯誤發(fā)生在運行時怀估。
代碼運行是解釋一行執(zhí)行一行碱工,沒有傳統(tǒng)語言的編譯過程,所以無法在執(zhí)行之前發(fā)現(xiàn)錯誤奏夫, 但是寫代碼的是人怕篷,人是不可能避免出現(xiàn)錯誤的。 - Javascript本身的語言特性酗昼, 它并不適合做大型項目廊谓。
所以在前端開發(fā)中,大部分時間都在排錯??麻削。
TypeScript
TypeScript
是JS
的一個超集蒸痹,是一個可選的,靜態(tài)的類型系統(tǒng)呛哟。TS
不是一門新的語言叠荠,js
代碼修改后綴為 ts
一樣可以正常執(zhí)行,超集的意思是: 男人扫责、女人榛鼎、小孩、大人,人是超集者娱。只要是人抡笼, 都在這個集合里面。
TypeScript
可以解決上述問題黄鳍。它會對代碼中的所有標識符(變量推姻、函數(shù)、參數(shù)框沟、返回值等)進行類型檢查和推導藏古。從而減少不必要的錯誤發(fā)生,換言之忍燥,開發(fā)過程中使用 ts
比 使用js
擁有更強的生產力拧晕。
2012 年由微軟發(fā)布并開源。
TS 代碼不能直接運行在各個環(huán)境中
TS
增加了一些特殊的語法來進行類型檢查灾前,所以防症,無論是瀏覽器還是Node
環(huán)境孟辑,都不能識別這些新增加的語法哎甲。需要通過 TSC (TypeScript Compiler )
編譯之后執(zhí)行。編譯之后是純粹的Javascript
代碼
開始吧
全局安裝 typescript 和 編譯器 tsc饲嗽,新建一個 ts 文件炭玫, 寫兩行代碼:
現(xiàn)在你還會因為類型錯誤浪費大量時間查錯而煩惱嗎?
function getNumber():number{
return 1
}
var width:number = 100;
再寫兩行代碼貌虾, ts 與 js 明顯的不同就是吞加,定義了變量、函數(shù)返回值的類型尽狠。如果返回的類型不是期望的類型衔憨,編輯器首先會提示報錯,如果對此置之不理袄膏,使用 tsc 編譯的時候會報錯践图。這就和強類型語言很像了,語法不對沉馆,編譯都不能通過码党。
function getNumber() {
return 1;
}
var width = 100;
使用tsc src/index/ts
編譯之后的代碼與正常的 js 一樣。
注意
默認情況下斥黑, ts 會作出如下假設:
- 假設當前執(zhí)行環(huán)境是 dom (瀏覽器環(huán)境)
- 代碼中如果沒有模塊化語句(import揖盘、export),便認為此代碼全局執(zhí)行
- tsc 編譯的目標代碼是 es3
有兩種方式更改上述默認設置:
- 使用 tsc 命令的時候加上參數(shù)
- 使用配置文件更改編譯選項锌奴,配置文件之后兽狭,直接使用 tsc 就可以了, 如果后面指定了文件夾,那么會忽略掉配置文件。
對變量以及函數(shù)的約束
// 約束變量
let name:string = "mike";
let age:number = 18;
// 約束函數(shù)
function add (a:number, b:number):number{
return a + b;
}
// 參數(shù)以及返回值的約束椭符,如果傳參和返回值類型不符合約束荔燎,會直接提示報錯
let number:number = add(1,2);
在很多場景下, ts 可以自行完成對某些變量類型的推導:
function add (a:number, b:number){
return a + b;
}
此函數(shù)返回的一定是一個number销钝, 這是確定的:
在每一個聲明有咨,賦值的地方,都會有類型檢查蒸健。
let a; // 這是一個 any 類型座享, 即任意類型, ts 不對 any 類型作類型檢查
基本類型約束
- number
- string
- boolean
- null 和 undefined
這兩個比較特殊似忧, 它倆不用作類型約束渣叛, 是所有類型的子類型,一個被定義為某個確定類型的變量可以被賦值為 null 和 undefined盯捌。
但是這樣會引發(fā)問題:
let str:string = undefined;
str.toUpperCase() ????
是不是會出問題淳衙? 所以對于這個情況,一般是不允許這么做的饺著,我們可以在編譯選項中設置 嚴格的空類型檢查
"strictNullChecks": true
復雜類型約束
- 數(shù)組
// 約束數(shù)組
let arr:number[];
let arr: Array<number>[];
- 對象
let obj:object;
// obj 只能被賦值為一個對象箫攀,但是無法深入定制對象里面屬性的類型
- 聯(lián)合類型
有時候,比如一個用戶的名字幼衰, 它可能是一個字符串靴跛,也可能還沒有填寫, 這時候是可以為 undefined 的渡嚣,此時可以使用聯(lián)合類型
let name:string | undefined = undefined;
當
ts
不確定類型的時候梢睛,你想象的這個類型對應的方法,不會給你智能提示识椰。所以這里經過了判斷绝葡,如果names 的是string
類型, 才會給出對應的智能提示腹鹉, 因為代碼執(zhí)行藏畅, 如果進了這個判斷, 這個names
一定是string
類型了种蘸。這也提醒我們墓赴, 如果在用 ts
開發(fā)過程中,你想使用某個方法卻沒有智能提示的時候航瞭, 就要小心了诫硕, 類型可能出問題了。
- void 類型: 通常用于約束函數(shù)的返回值刊侯, 表示不返回任何值章办。
funtion f():void{
return 1;
}
// 說一不二的 ts, 如果規(guī)定了此函數(shù)不返回值, 如果返回了也會報錯藕届。
- never : 通常用來約束函數(shù)的返回值挪蹭, 表示這個函數(shù)永遠不可能結束
函數(shù)結束的定義式最后一行代碼執(zhí)行完畢
function do():never{
while(true){}
}
- 字面量約束
這意思很清楚了,將變量a
以字符串“A”
約束休偶,從此a只能是“A”
let sex: "男" | "女";
let user: {
name: string,
sex: "男" | "女",
age: number
}
// 注意 user 后面不是等號梁厉, 不是賦值, 這里是使用字面量的形式約束user
- 元組約束
var tuple: [string, number]
約束 tuple 必須是一個數(shù)組踏兜, 數(shù)組有且只能有兩項词顾, 第一項為字符串, 第二項為數(shù)字碱妆。
- any: 此類型可繞過類型檢查肉盹。可以賦值為任意類型疹尾。
類型別名
type User = {
name: string,
sex: 'male' | 'female',
age: number
}
// 函數(shù)返回一個 User 類型的數(shù)組上忍。
function getUsers ():User[]{
return []
}
函數(shù)相關約束
這里有個函數(shù), 接收兩個參數(shù)纳本。 如果這兩個參數(shù)都是數(shù)字窍蓝, 返回二者的乘積, 如果二者都是字符串饮醇, 拼接返回它抱。
function combine (a: number|string, b: number|string):number|string{
if(typeof a === 'number' && typeof b === 'number'){
return a * b;
}
if(typeof a === 'string' && typeof b === 'string'){
return a + b;
}
throw "a and b should be a same type";
}
let res = combine(1, 2)
我傳入了兩個數(shù)字秕豫,很明顯返回值肯定是一個
number
朴艰, 但是系統(tǒng)提示res 可能是 string
或者number
。 這是不符合我們要求的混移。 我們希望祠墅, 傳兩個相同類型的值做出對應的確定的回應。
function combine(a: number, b:number):number;
function combine(a: string, b:string):string;
function combine (a: number|string, b:number|string) :number|string{
if(typeof a === 'number' && typeof b === 'number'){
return a * b;
}
if(typeof a === 'string' && typeof b === 'string'){
return a + b;
}
throw "a and b should be a same type";
}
let res = combine(1, 2)
這下確定了歌径!我們使用聲明式的約束毁嗦,明確指出,同number
返回number
回铛。這類似于 Java
的重載狗准。
可選參數(shù) & 默認參數(shù)
function sum(a: number, b: number = 0, c?: number){
return c ? a + b + c : a + b;
}
在參數(shù)名之后,添加一個 茵肃?腔长,表示該參數(shù)可選。
在參數(shù)聲明完成后验残, 可以為參數(shù)添加默認值:b: number = 0
枚舉
enum Gender {
male = "男",
female = "女"
// 邏輯名稱 = 真實值
}
- 數(shù)字類型的枚舉捞附,默認會自增,如果不賦值, 默認從0開始自增鸟召。
enum Level {
normal = 1,
vip, // 2
svip, // 3
s_svip // 4
}
================================================
(前端知識博大精深胆绊,僅作為自己備忘,不作為教程 )