1. 程式人生 > 其它 >(二)typescript之型別檢查

(二)typescript之型別檢查

一、​基本型別檢查

1.型別約束可以約束變數、函式引數、函式返回值

1 let age: number = 18;
2 age = 19;
3 function sum(a: number, b: number): number {
4   return a+b;
5 }
6 let num:number = sum(3, 4);

tips:使用快捷鍵f2可以重新命名函式,快捷鍵f12可以快速跳轉至函式定義

2.基本資料型別和引用資料型別的型別約束

 1 // 數字型別
 2 let age: number = 18;
 3 // 布林型別
 4 let flag: boolean = true
; 5 // 字串型別 6 let name: string = 'pengyuyan'; 7 // null 8 let nullValue: null = null; 9 // undefined 10 let undefinedValue: undefined = undefined; 11 // object 12 let obj: object = {}; 13 // 陣列型別 14 let nums1: number[] = [1,2,3]; 15 let nums2: Array<number> = [3,4,5];

tips: undefined和null預設可以賦值給任意型別,若需要使用更嚴格的空型別檢查,需要在tsconfig新增配置:strictNullChecks: true

3.其他常用型別

 1 // 聯合型別
 2 let name: string | undefined = undefined;
 3 // void 約束函式返回值,表示該函式沒有任何返回
 4 function print(): void {
 5   console.log(111)
 6 }
 7 // never 約束函式返回值,表示該函式永遠不可能結束
 8 function throwError(msg: string): never {
 9   throw new Error(msg);
10 }
11 // 字面量型別 使用一個值進行約束
12 let gender: "男" | "女";
13 gender = "男"; 14 let user: { 15 name: string 16 age: number 17 } 18 // 元祖型別(Tuple) 一個固定長度的陣列,並且陣列中的每一項的型別確定 19 let tu: [string, number]; 20 tu = ["3", 4]; 21 // any型別 any型別可以繞過型別檢查,any型別的資料可以賦值給任意型別。 22 ​let data: any = "asaass"; 23 let num: number = data;

4.函式相關約束

(1)函式過載
圖片

對於上圖中的result1,我們理想得到的結果應該是這樣的:如果兩個引數都是數字型別,那麼推斷出的返回結果也應該是數字型別;兩個引數是字串時,同理。
但兩個引數都是數字型別時,圖中推斷的返回值卻是string | number型別,怎樣讓它能正確推斷出返回值是number型別呢?這就需要藉助函式過載來實現啦
 1 // 表示兩個引數都是number型別時,返回值為number型別
 2 function combine(a: number, b: number): number;
 3 // 表示兩個引數都是string型別時,返回值為string型別
 4 function combine(a: string, b: string): string;
 5 function combine(a: number | string, b: number | string)
 6 : number | string {
 7   if (typeof a === 'number' && typeof b === 'number') {
 8     return a * b;
 9   } else if (typeof a === 'string' && typeof b === 'string') {
10     return a + b;
11   }
12   throw new Error('a和b必須是相同的型別');
13 }
14 // 這樣的話result1就推斷出是number型別,result2則是string型別的
15 const result1 = combine(3, 3);
16 const result2 = combine('3', '3');

(2)可選引數

1 // 表示第2、3個引數可填可不填,且必須在引數列表的末尾
2 function sum(a: number, b?:number, c?:number) {
3 }
4 sum(1, 2, 3);
5 sum(1);

二、擴充套件型別

1.類型別名

 1 // type關鍵字 + 名字 = xxx
 2 type Gender = "男" | "女"
 3 type User = {
 4   name: string
 5   age: number
 6   gender: Gender
 7 }
 8 function getUsers(g:Gender):User[] {
 9   return [];
10 }
11

2.列舉

列舉通常用於約束某個變數的取值範圍

字面量和聯合型別配合使用,也可以達到同樣的目標

但是使用字面量型別時會有以下的問題:

1 // 型別約束的位置,會產生重複的程式碼
2 let gender: 'man' | 'female'
3 gender = 'man';
4 function getUsers(g: 'man' | 'female') {
5    // do()
6 }

可使用類型別名解決以上問題

1 type Gender = 'man' | 'female'
2 let gender: Gender = 'man';
3 function getUsers(g: Gender) {
4  // do()
5 }
6

但是類型別名也會有另外的問題

問題一:邏輯名稱和真實的值產生了混淆,會導致當修改真實值的時候,產生大量的修改

1 // man和female可能還會有很多種不同的取值,比如“男”“女”,“帥哥”“美女”,但它們的
2 // 邏輯含義其實都是一樣的,但是賦值的時候只能賦真實的值,所以一旦真實值換種寫法,
3 // 就會導致大量的真實值的更改
4 type Gender = 'man' | 'female'
5 let gender: Gender = 'man';
6 let gender1: Gender = 'man';
7 let gender2: Gender = 'female';
1 type Gender = '男' | '女'
2 let gender: Gender = '男';
3 let gender1: Gender = '男';
4 let gender2: Gender = '女';

問題二:型別不會進入編譯結果無法檢視Gender的具體值有哪些

圖片

可使用列舉解決以上問題

 1 // 修改真實值,只需要修改列舉值,不用修改大量真實值
 2 enum Gender {
 3   male = "男",
 4   female = "女",
 5 }
 6 let gender: Gender = Gender.male;
 7 let gender1: Gender = Gender.male;
 8 let gender2: Gender = Gender.female;
 9 // 可以直接訪問列舉值
10 console.log('Gender: ', Gender);

列舉的規則

(1)列舉的值可以為字串或者數字

 1 // 若第一個列舉值為數字,後面的值會自動自增
 2 enum Level {
 3   level1 = 2,
 4   level2,
 5   level3,
 6 }
 7 let l2: Level = Level.level2;
 8 let l3: Level = Level.level3;
 9 console.log('l2: ', l2);// 3
10 console.log('l3: ', l3);// 4
11 // 若沒有設定值,則第一個預設值為0,後面值依次遞增
12 enum Level {
13   level1, // 0
14   level2, // 1
15   level3, // 2
16 }
17

(2)字串列舉和數字列舉的編譯結果不同

 1 // 字串列舉
 2 enum Gender {
 3   male = "男",
 4   female = "女",
 5 }
 6 console.log('Gender: ', Gender);
 7 // 數字列舉
 8 enum Level {
 9   level1 = 2,
10   level2,
11   level3,
12 }
13 console.log('Level: ', Level);

列印結果為:

圖片

使用列舉時需要注意:

儘量不要再一個列舉中既出現字串欄位,又出現數字欄位

1 // ❌ 不建議
2 enum Level {
3   level1 = 2,
4   level2 = "a",
5 }

使用列舉時,儘量使用列舉的名稱,而不使用真實的值

1 function getUsers(l: Level.level1) {
2 3 }
4 getUsers(Level.level1);