寫在前面:javascript
由於typescript文檔我的感受寫得很差(概念過於雜亂,示例代碼有錯誤~)。因此總結一下TS的知識java
這是我的學習筆記總結,並無官方文檔嚴謹。更多的是我的的大白話react
代碼部分 推薦各位複製到支持TS的代碼編輯器裏 看看什麼效果。體驗一下 TS在編譯階段的嚴謹~~typescript
想學習TypeScript的朋友能夠快速掃兩眼,入個門~ json
首先typescript的基礎數據類型:redux
布爾類型(boolean)
數組
數字類型(number)
dom
字符串類型(string)
編輯器
數組類型(array)
函數
元組類型(tuple)
枚舉類型(enum)
任意值類型(any)
null 和 undefined
void類型
never類型
object 類型
類型斷言
Symbol 類型
布爾類型是最簡單的數據類型,只能賦值爲true
和false
兩種值,不能賦予其餘的值
類型註解: 其實就是指定各類類型, boolean, string之類的。其餘語言也叫類型註解 因此統一一下
基礎語法:
變量:類型註解 = 對應類型註解的值
let bol: boolean = true
let bol2: boolean
bol2 = false
bol = blo2 // 能夠 bol是boolean類型 因此能夠賦值false
bol = ' 1' //Type '"1"' is not assignable to type'boolean'. 字符串不能賦值給boolean類型
複製代碼
除了規定了變量類型以外,其餘語法與javascript同樣。
和JavaScript同樣,TypeScript數字都是浮點型( 1 在JS眼裏是 1.0),也支持二進制、八進制、十進制和十六進制
let num1: number = 123 //十進制
num1 = 0b01111011 //二進制 0b開頭 ES6引入
num1 = 0o173 //八進制 0o開頭 ES6引入
num1= 0x7b //十六進制 0x開頭
如下是特殊的number類型:
num1 = Infinity //無窮大
num1 = -Infinity //負無窮大
num1 = NaN //Not a Number
複製代碼
被""
,''
和ES6模板字符串\` `
.包裹起來的值,都是字符串類型
let str: string = '哈哈哈'
let str2: string = `笑聲${str}`
複製代碼
TypeScript 提供了兩種定義數組類型的方法。一種是在類型
後加上 []
表示這是一個數組。 推薦優先使用這種寫法
語法:
let 變量:類型註解[]
let arr1: number[] //number類型數組,只能存number類型
arr1 = [5,1,3] // true
arr1 = ['1'] // false 只能夠賦值number類型
複製代碼
另外一種方法是使用泛型表示:Array < T>
,其中 T 爲數組中元素的類型。
語法:
let 變量:Array<T> //這裏的 <T> 代指泛型。 能夠簡單的理解爲就是一個佔位符,'暫時'沒有實際的類型。類型根據使用時傳入的值而定。泛型後續會詳解
let arr2 : Array<string> //string 數組
arr = ['1','a','haha']
let arr3 : Array<boolean> = [true,false,true] //boolean數組
複製代碼
元組類型就是一個特殊的數組。
表示已知數量
和已知元素類型
的數組, 裏面的每一項能夠是不一樣的類型
語法:
let 變量:[類型1,類型2....]
let arr : [string, number, boolean,number[]]
//1.數量固定,只能傳四個元素,不可少傳也不可多傳
//2.各索引位的元素類型固定,不可改變。
arr = ['1', 2, true, numArr] // true 必須按照 固定數量和類型順序賦值
如下是錯誤寫法:
arr = [1, 2, true, numArr] //error 第一個位置接收string類型,卻傳入number。類型不匹配
arr = [1, '2', true, numArr] //error 同上 ,前兩個位置類型不匹配
arr = ['2'] // error arr必須接受4個參數,這裏只傳入一個
arr = [1, '2', true, numArr, 2] // error 傳入過多的參數也不行,最後一個爲越界元素。如今數組的length爲4,不能傳入第五個值
複製代碼
枚舉用來表示一些邏輯上有關聯的數據,而且這些數據不能被修改的。讓這些數據更有語義化。
枚舉類型裏面的值都是隻讀的,只能讀取不能修改
語法:
enum 標識符 {
值,
值
...
}
------------------------------------------------------
//應用場景:假設根據後臺傳入數據,讓咱們來判斷用戶權限操做
//傳遞的數據裏有id。id存儲的number類型的數據,咱們依次來判斷
roles = {
id:xxx,
...
}
//無語義化寫法:
switch(roles.id) {
case 0:
//普通用戶
break;
case 1:
//員工
break;
case 2:
//管理員
break;
}
//缺點須要寫文檔註釋,代表0 , 1...是什麼意思
//使用枚舉,定義一組用戶數據:
enum Roles {
USER, //0
STAFF, //1
ADMIN //2
}
// 每一個枚舉類型的值,都有對應的索引值,默認從0開始依次遞增
// 取值操做相似於JS對象
Roles.USER // 0 經過屬性取索引
Roles[0] // USER 經過索引取屬性值 下面會解釋是如何實現的
// 使用Roles來做爲判斷條件
switch(roles.id) {
case Roles.USER: // 0
//普通用戶
break;
case Roles.STAFF: // 1
//員工
break;
case Roles.ADMIN: // 2
//管理員
break;
}
// 更有語義化,代碼直觀易讀
--------------------------------------------------------------------------------------------------------------------
// 將枚舉類型,轉化爲JS。看是如何實現的
enum Roles {
USER, //0
STAFF, //1
ADMIN //2
}
//JS代碼
var Roles;
(function (Roles) {
Roles[Roles["USER"] = 0] = "USER";
Roles[Roles["STAFF"] = 1] = "STAFF";
Roles[Roles["ADMIN"] = 2] = "ADMIN";
})(Roles || (Roles = {}));
解析:
首先Roles是個對象,而後當即執行函數會對這個對象進行賦值
Roles[Roles["USER"] = 0] = "USER";
能夠分解爲:
首先給Roles設置一個 USER 的屬性,賦值爲0
Roles["USER"] = 0 //這步操做是有返回值的 返回值就是 = 右邊的值 此處爲0, ~~能夠測試自行建立一個對象,再賦值看返回的結果
而後將上一步的返回值做爲屬性名,再次賦值
Roles[0] = "USER"
因此能夠經過索引或屬性名取相互的值,很是巧妙
Roles[0] // USER
Roles["USER"] // 0
--------------------------------------------------------------------------------------------------------------------
// 在定義枚舉時,能夠自定義索引值
enum English {
A = 1, // 1
B, // 2
D = 4, // 4
E // 5
}
let a = English.A // 1
let c = English.B // 2
let d = English.D // 4
let e = English.E // 5
let eng = English[5] // E
//自定義索引值只會影響,後續值的索引值(自動根據前一個增長)
enum english {
a, // 默認值 0
b = 2, // 2 影響排在其後的元素
c, // 3
d, // 4
e // 5
}
english.a = 1 //error 枚舉類型裏的值是隻讀類型,只容許讀取
english[a] //error 枚舉類型裏面的值,是字符串。這樣取值是錯誤的,會去找同名變量,進行操做。
english['a'] //ok
------------------------------------------------------------------------------------------------------------------
枚舉類型,後續還有不少用法。好比說使用redux時,用來存儲Action的type
複製代碼
any
表示任意類型,任何值均可以傳入any
。
any類型
上是類型系統的逃生艙口(走後門)。TS不會對any類型進行檢查
萬物皆any~
let value: any;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OK
value = Symbol("type"); // OK
// 如今變量能夠任意賦值,和原生JS平時操做沒有任何限制同樣
--------------------------------------------------------
let anyArr: any[] = [1,24,5,'hhh',['qqq'],true]
// 雖然方便,但儘可能少使用。否者就失去了使用TS的意義,沒有類型檢查的保障,代碼容易出問題。
// 通常在將JS代碼重構爲TS時,使用的較多
複製代碼
void
表示沒有任何類型, 經常使用在函數沒有返回值的狀況下指定,表示一個函數沒有返回值
// 例子:
let func = (name:string):void => {
console.log(`hello, $(name)`)
// 這個函數沒有指定任何返回值
// 但在JS裏 函數都會默認返回undefined。void會默認兼容undefined類型
}
func(456) // error 參數必須是是string類型。這就體現了TS的好處了,編譯階段就會提醒錯誤
func('Bob') // true
let num:void
num = undefined //true
num = null //error
num = 1 // error
let V: any;
num = V // true 再次強調 any類型能夠兼容其餘全部類型(除never外)~
void 大部分場景用在函數的返回值類型上,關於函數的知識後續會講解
複製代碼
1.在TS中null
和 undefined
既是類型,也能夠做爲普通的值使用。參考上面函數默認返回值undefined
2.在TS非嚴格模式下null
和undefined
同時也是其餘類型的子類型(其餘類型能夠兼容這兩個值), 嚴格模式下會報錯
tsconfig.json(ts配置文件):strict: false (非嚴格模式下)(其中一個選項,默認是true 嚴格模式):
let isNull: null // null類型只能接收 null類型 和 undefined類
let isUndefined: undefined // undefined類型只能接收 undefined類型 和 null類型
isNull = null //true
isNull = 1 //error
isNull = undefined //true
isUndefined = null //true
isUndefined = undefined //true
isUndefined = '2' //error
let str: string
str = null //true
str = undefined //true
--------------------------------------------------------------
tsconfig.json:strict: true (嚴格模式下):
let isNull: null // null類型只能接收null值
let isUndefined: undefined // undefined類型只能接收undefined值
isNull = null //true
isNull = 1 //error
isNull = undefined //error
isUndefined = null //error
isUndefined = undefined //true
isUndefined = '2' //error
let str: string
str = null //error 嚴格模式下報錯,不能做爲子類型
str = undefined //error
複製代碼
never
類型比較抽象,表示永遠不存在的值
非嚴格模式下never
類型是任何類型的子類型,也能夠賦值給任何類型.
//常見的兩種狀況 拋出錯誤和死循環
const errorFunc = (message: string): never => {
throw new Error(message)
}
const infiniteFunc = ():never => {
while(true){}
}
------------------------------------------------------
tsconfig.json中:strict: false (非嚴格模式下):
let str: string
let isNever: never
str = isNever // true
isNever = str //error
複製代碼
object
類型,就是用來表示引用類型的。與JS對象無差異
let obj = {
name: 'Bob'
}
obj.sex = 'man'
const getObject = (obj: object):void => {
console.log(obj)
}
getObject('hahah') // error
getObject(obj) // true
複製代碼
混淆是非,把某個值,強制指定爲咱們須要的類型,TS就會按照咱們指定的類型進行檢查
能夠理解爲 相似於強制類型轉換。只是相似┗|`O′|┛ 嗷~~
語法: 兩種寫法。
1. <類型>值
2. 值 as 類型 //react技術棧 編寫JSX時,必須使用這個。上面的和JSX語法有歧義
// 需求 有個函數接收一個string或者number類型的值。
// 若是是string 咱們直接返回字符串的長度
// 若是是number 我門把number轉化爲字符串,在返回長度
const getLength = (target: string | number): number => {
// target的類型能夠是string或number. 這是聯合類型的語法。後續會講解
if(target.length) { //提示錯誤
return target.length //提示錯誤
} else {
return target.toString().length
}
}
getLength(1) // 正常
getLength('hh') //正常
// 上面的代碼,邏輯沒有問題。
// 但在TS寫代碼過程當中就會提示錯誤,TS會認爲這個代碼是有問題的。首先編譯階段參數類型還沒肯定,會把number 和 string 都做爲參數類型進行檢測
// string有length屬性能夠經過。number沒有length屬性,因此TS在編譯階段就會提示number沒有length屬性。
// 代碼能正常編譯爲JS,也能正常運行。由於JS是運行時纔會檢測代碼。但一直提示錯誤 屬實很差看
//使用類型斷言解決這個問題。
const getLength2 = (target: string | number): number => {
// 把<string>target,把target指定爲了string類型,這樣代碼就會按照string類型就行檢測。
if((<string>target).length) { return (target as string).length //同上 類型斷言第二種寫法,加()是由於運算符優先級的問題 } else { return target.toString().length } } getLength2(1) //ok //若是傳入number類型,運行階段仍是會走 toString 那行代碼。 //類型斷言並非說把target轉化爲string類型了。僅僅是在編譯階段 讓TS跟着你指定的類型進行檢測 getLength2('hh') //ok 複製代碼
Symbol 類型
的講解推薦去看阮一峯老師的ES6入門教程。TS基本上與ES6沒有多大區別 除了TS擴展的類型~,因此人們常說ES6學好了,學TS會很容易