一,TS的資料型別
ES6的資料型別:
6種基本資料型別
Boolean
Number
String
Symbol
undefined
null
3種參考型別
Array
Function
Object
TS的資料型別:
TS在ES6基礎上,又新增了以下資料型別
void
any
never
元組
列舉
高級型別
除此之外,TS還有很多型別的高級使用技巧
二,型別注解
TS可以通過型別注解對變數型別進行約束
TS和JS最主要的區別:變數的資料型別不可改變
語法: 變數/函式 : type
如: let hello : string = 'Hello TypeScript'
三,原始型別
let bl: boolean = true
let num: number = 123
let str: string = "123"
使用型別注解對變數進行型別約束后,再進行不恰當的賦值就會報錯
四,陣列型別
在 TypeScript 中,陣列型別有多種定義方式,主要有一下三種定義方法:
1、「型別 + 方括號」表示法
let tsArray: number[] = [1,1,2,3,4]
陣列中的項中不允許出現其他型別
let fibonacci: number[] = [1, '1', 2, 3, 5]; //報錯
上例中,[1, '1', 2, 3, 5] 的型別被推斷為 (number | string)[],這是聯合型別和陣列的結合,
陣列的一些方法的引數也會根據陣列在定義時約定的型別進行限制:
let fibonacci: number[] = [0, 1, 2, 3, 5]; fibonacci.push('6'); // index.ts(2,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
上例中,push 方法只允許傳入 number 型別的引數,但是卻傳了一個 string 型別的引數,所以報錯了,
2、陣列泛型
使用陣列泛型(Array Generic) Array<elemType> 來表示陣列:
let arrType: Array<number> = [0, 1, 2, 3, 5]; let arrType1: Array<string> = ['0', '1', '2', '3', '5']; let arrType2: Array<any> = [1, '1', 2, 's', true];
3、用介面表示陣列
interface Person{ name: string; age: number; } interface NumberArray { [index:number]: Person; } let arrType3: NumberArray = [{name:'張三',age: 20}] let arrType4:Array<Person> = [{name:'張三',age: 20}] let arrType5:Person[] = [{name:'張三',age: 20}]
NumberArray 表示:只要 index 的型別是 number,那么值的結構型別必須是符合Person介面,
類陣列(特別注意)
類陣列(Array-like Object)不是陣列型別,比如 arguments:
function sum() {
let args: number[] = arguments;
}
// index.ts(2,7): error TS2322: Type 'IArguments' is not assignable to type 'number[]'.
// Property 'push' is missing in type 'IArguments'.
事實上常見的類陣列都有自己的介面定義,如 IArguments, NodeList, HTMLCollection 等:
function sum() {
let args: IArguments = arguments;
}
五,元組型別
是一種限制陣列的元素型別和個數的陣列
let tuple: [number, string] = [0, '1']
此時,如果改變陣列的元素型別或添加元素數量,編輯器都會報錯:
let tuple: [number, string] = [0, 1] //Type 'number' is not assignable to type 'string'. let tuple: [number, string] = [0, '1', '2'] //報錯: Type '[number, string, string]' is not assignable to type '[number, string]'. Types of property 'length' are incompatible. Type '3' is not assignable to type '2'.
元組越界問題:
雖然元組限制了陣列元素的型別和數量,過多的元素宣告會報錯
但TS允許向元組中使用陣列的push方法插入新元素(但不允許訪問)
let tuple: [number, string] = [0, '1'] tuple.push(2) console.log("tuple.push(2)", tuple) // tuple.push(2) (3) [0, "1", 2]
但不允許訪問:
tuple.push(2) // 可越界添加 tuple[2] // 不可越界訪問 //報錯: //Tuple type '[number, string]' of length '2' has no element at index '2'.
六,函式
在 JavaScript 中,有兩種常見的定義函式的方式——函式宣告(Function Declaration)和函式運算式(Function Expression):
// 函式宣告(Function Declaration)
function sum(x, y) {
return x + y;
}
// 函式運算式(Function Expression)
let mySum = function (x, y) {
return x + y;
};
1、函式宣告
一個函式有輸入和輸出,要在 TypeScript 中對其進行約束,需要把輸入和輸出都考慮到,其中函式宣告的型別定義較簡單:
function sum(x:number,y:number):number{
return x+y
}
注意,輸入多余的或者少于要求的引數,是不被允許的
sum(1, 2, 3); // index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
sum(1); // index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
2、函式運算式
如果要我們現在寫一個對函式運算式(Function Expression)的定義,可能會寫成這樣
let mySun = function(x:number,y:number):number{
return x + y
}
這是可以通過編譯的,不過事實上,上面的代碼只對等號右側的匿名函式進行了型別定義,而等號左邊的 mySum,是通過賦值操作進行型別推論而推斷出來的,如果需要我們手動給 mySum 添加型別,則應該是這樣:
let mySum(x:number,y:number)=>number = function(x:number,y:number):number{
return x+y}
注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>,
在 TypeScript 的型別定義中,=> 用來表示函式的定義,左邊是輸入型別,需要用括號括起來,右邊是輸出型別,
在 ES6 中,=> 叫做箭頭函式,應用十分廣泛,
3、用介面定義函式的形狀
我們也可以使用介面的方式來定義一個函式需要符合的形狀:
interface SearchFunc{
(source:string,subString:string):boolean
}
let mySearch:SearchFunc;
mySearch = function(source: string,subString:string){
return source.search(subString) !== -1
}
函式入參
1、可選引數
前面提到,輸入多余的(或者少于要求的)引數,是不允許的,那么如何定義可選的引數呢?
與介面中的可選屬性類似,我們用 ? 表示可選的引數:
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
注意:可選引數必須接在必需引數后面,換句話說,可選引數后面不允許再出現必須引數了
2、引數默認值
在 ES6 中,我們允許給函式的引數添加默認值,TypeScript 會將添加了默認值的引數識別為可選引數:
function buildName(firstName:string,lastName:string='Cat'){
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
此時就不受「可選引數必須接在必需引數后面」的限制了:
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');
3、剩余引數
ES6 中,可以使用 ...rest 的方式獲取函式中的剩余引數(rest 引數):
function push(array,...items){
items.forEach(function(item){
array.push(item)
})
}
let a = [];
push(a,1,2,3)
事實上,items 是一個陣列,所以我們可以用陣列的型別來定義它:
function push(array:any[],...items:any[]){
items.forEach(function(item){
array.push(item);
})
}
let a = []
push(a,1,2,3)
注意:rest 引數只能是最后一個引數
多載:
多載允許一個函式接受不同數量或型別的引數時,作出不同的處理,
比如,我們需要實作一個函式 reverse,輸入數字 123 的時候,輸出反轉的數字 321,輸入字串 'hello' 的時候,輸出反轉的字串 'olleh',
利用聯合型別,我們可以這么實作:
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
然而這樣有一個缺點,就是不能夠精確的表達,輸入為數字的時候,輸出也應該為數字,輸入為字串的時候,輸出也應該為字串,
這時,我們可以使用多載定義多個 reverse 的函式型別:
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
上例中,我們重復定義了多次函式 reverse,前幾次都是函式定義,最后一次是函式實作,在編輯器的代碼提示中,可以正確的看到前兩個提示,
注意:TypeScript 會優先從最前面的函式定義開始匹配,所以多個函式定義如果有包含關系,需要優先把精確的定義寫在前面,
七,物件
在JS中,可以任意修改物件屬性,TS中不允許
let obj: object = {x: 'a', y: 'b'}
obj.x = 3 // Property 'x' does not exist on type 'object'.
這是因為,僅宣告了物件obj的型別注解是object,
并沒有為物件內部的具體屬性(屬性名)和型別做限制
let obj: {x: string, y: string} = {x: 'a', y: 'b'}
obj.x = 'c'
還可以使用介面的形式來規范物件,介面會在下一篇隨筆介紹,
八,Symbol
具有唯一的值
可以顯式宣告,也可直接創建
let symbol1: Symbol = Symbol() // 顯示宣告 let symbol2 = Symbol() // 直接創建 // 驗證:是否是同一個物件 console.log(symbol1 === symbol2) // fasle
九,undefined 和 null
let udf: undefined = undefined let nu: null = null
一旦宣告了undefined,就不能再被賦值為任何其他的資料型別了:
let undf: undefined = 1 // Type '1' is not assignable to type 'undefined'.
默認情況下,undefined和null也不能被賦值給任何其他型別:
// 驗證:undefined和null也能被賦值給任何其他型別 let num1: number = undefined // Type 'undefined' is not assignable to type 'number'. let num2: number = null // Type 'null' is not assignable to type 'number'.
允許undefined和null被賦值其他型別:
在TS中,undefined和null是任何型別的子型別,所以可以被賦值給其他型別
設定允許被賦值為其他型別
打開tsconfig.js,將strictNullChecks = false(默認true)

在不修改此配置的情況下,實作對undefined和null的賦值,可使用聯合型別
let num3: number | undefined | null = 111
十,void
在js中,void運算子可以使任何一個運算式回傳undefined
void 0 // 將回傳undefined
在TS中,void型別表示沒有回傳值,沒有回傳值的函式,他的型別就是void型別
// void let voidFunc = () => {}
十一,any
any:如果不指定TS的變數型別,默認為any型別,可以賦值為任何型別
let x x = 1 // 整型 x = [] // 陣列 x = () => {} // 函式
不建議使用any型別,將失去使用ts的意義
十二,never
never:永遠不會有回傳值的型別
1,函式拋出例外,永遠不會有回傳值,型別為never
// 函式拋出例外,永遠不會有回傳值,型別為never let error = () => { throw new Error('error') }
2,死回圈函式永遠沒有回傳值,型別為never
// 死回圈函式永遠沒有回傳值,型別為never let endless = () => { while(true) {} }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/260913.html
標籤:JavaScript
