第三節:TypeScript類型補充和函數詳解(參數、返回值、類型、參數【可選/默認】、剩余參數、this、重載)


一. TypeScript類型補充

1. 類型斷言

 有時候TypeScript無法獲取具體的類型信息,這個我們需要使用類型斷言(Type Assertions) ,TypeScript只允許類型斷言轉換為 更具體 或者 不太具體 的類型版本,此規則可防止不可能的強制轉換。

 符號:as

// 1.類型斷言 as
const el = document.getElementById("why") as HTMLImageElement
el.src = "url地址"

// 2.另外案例: Person是Student的父類
class Person { }
class Student extends Person {
    studying() { }
}
function sayHello(p: Person) {
    (p as Student).studying()
}
const stu = new Student()
sayHello(stu)

2. 非空斷言

 我們確定傳入的參數是有值的,這個時候我們可以使用非空類型斷言。非空斷言使用的是 ! ,表示可以確定某個標識符是有值的,跳過ts在編譯階段對它的檢測

 符號:!

// message? -> undefined | string
function printMessageLength(message?: string) {
    // if (message) {
    //   console.log(message.length)
    // }
    // vue3源碼中很多這種寫法
    console.log(message!.length)
  }
  
  printMessageLength("aaaa")
  printMessageLength("hello world")

3. 可選鏈

 可選鏈事實上並不是TypeScript獨有的特性,它是ES11(ES2020)中增加的特性:

 符號  ?.

   它的作用是當對象的屬性不存在時,會短路,直接返回undefined,如果存在,那么才會繼續執行,  雖然可選鏈操作是ECMAScript提出的特性,但是和TypeScript一起使用更版本。

// 定義類型  
type Person = {
    name: string
    friend?: {
        name: string
        age?: number,
        girlFriend?: {
            name: string
        }
    }
}

// 聲明對象
const info: Person = {
    name: "why",
    friend: {
        name: "kobe",
        girlFriend: {
            name: "lily"
        }
    }
}


// 另外一個文件中
console.log(info.name)
// console.log(info.friend!.name)
console.log(info.friend?.name)
console.log(info.friend?.age)
console.log(info.friend?.girlFriend?.name)
View Code

4. !!運算符

 將一個其他類型轉換成boolean類型;類似於Boolean(變量)的方式;

const message = "Hello World"

// const flag = Boolean(message)
// console.log(flag)

const flag = !!message
console.log(flag)

5. ??運算符

 它是ES11增加的新特性;

 空值合並操作符??)是一個邏輯操作符,當操作符的左側是 null 或者 undefined 時,返回其右側操作數,否則返回左側操作數 。

let msg1: string | null = 'hello ts';
let msg2: string | null = null;

const result1 = msg1 ?? 'hello js';
// 上面等價於
const result2 = msg1 ? msg1 : 'hello js';
console.log(result1);
console.log(result2);

const result3 = msg2 ?? 'hello js';
// 上面等價於
const result4 = msg2 ? msg2 : 'hello js';
console.log(result3);
console.log(result4);

6. 字面量

 字面量類型(說白了就是自己聲明了一個類型)
// 1. 如下,這里聲明的字面量類型為 'hello ts'
let msg1: 'hello ts' = 'hello ts';
// msg1='hhh';   //報錯,類型錯誤,因為這里的類型是hello ts

//2. 字面量類型的意義, 就是必須結合聯合類型
type Alignment = 'left' | 'right' | 'center'

let align: Alignment = 'left'
align = 'right'
align = 'center'

7. 類型縮小

 在給定的執行路徑中,我們可以縮小比聲明時更小的類型,這個過程稱之為 縮小;

 常見的類型保護有如下幾種:

  A. typeof

  B. 平等縮小(比如===、!==)

  C. instanceof  (檢查一個值是否是另一個值的“實例” )

  D. in

// 1.typeof的類型縮小
type IDType = number | string
function printID(id: IDType) {
    if (typeof id === 'string') {
        console.log(id.toUpperCase())
    } else {
        console.log(id)
    }
}

// 2.平等的類型縮小(=== == !== !=/switch)
type Direction = "left" | "right" | "top" | "bottom"
function printDirection(direction: Direction) {
    // 1.if判斷
    // if (direction === 'left') {
    //   console.log(direction)
    // } else if ()

    // 2.switch判斷
    // switch (direction) {
    //   case 'left':
    //     console.log(direction)
    //     break;
    //   case ...
    // }
}

// 3.instanceof  檢查一個值是否是另一個值的“實例”
function printTime(time: string | Date) {
    if (time instanceof Date) {
        console.log(time.toUTCString())
    } else {
        console.log(time)
    }
}

class Student {
    studying() { }
}
class Teacher {
    teaching() { }
}
function work(p: Student | Teacher) {
    if (p instanceof Student) {
        p.studying()
    } else {
        p.teaching()
    }
}
const stu = new Student()
work(stu)

// 4. in(用於確定對象是否具有帶名稱的屬性:in運算符,如果指定的屬性在指定的對象或其原型鏈中,則in 運算符返回true;)
type Fish = {
    swimming: () => void
}
type Dog = {
    running: () => void
}
function walk(animal: Fish | Dog) {
    if ('swimming' in animal) {
        animal.swimming()
    } else {
        animal.running()
    }
}

const fish: Fish = {
    swimming() {
        console.log("swimming")
    }
}
walk(fish)
View Code

 

二. TypeScript函數詳解

1. 函數自身 參數類型 和 返回值類型

// 1. 函數的參數類型
function sum1(num1: number, num2: number) {
    return num1 + num2;
}

// 2. 函數的返回值類型
// 添加返回值的類型注解,這個注解出現在函數列表的后面:
function sum2(num1: number, num2: number): number {
    return num1 + num2;
}
// 和變量的類型注解一樣,我們常情況下不需要返回類型注解,因為TypeScript會根據 return 返回值推斷函數的返回類型:
function sum3(num1: number, num2: number) {
    return num1 + num2;
}

2. 作為參數的函數類型

 可以編寫函數類型的表達式(Function Type Expressions),來表示函數類型;

 格式為:  (n:xx,m:xx)=>xxx括號里的是參數名和參數類型=>后面的是返回值類型比如: (num1: number, num2: number) => void,代表的就是一個函數類型:

 A. 接收兩個參數的函數:num1和num2,並且都是number類型;

 B. 並且這個函數是沒有返回值的,所以是void;

// 案例1-函數作為參數進行傳遞
function calc(m1: number, m2: number, fn: (num1: number, num2: number) => number) {
    return fn(m1, m2);
}
const result1 = calc(10, 20, function (m, n) {
    return m - n;
})
console.log(result1);
const result2 = calc(10, 20, function (m, n) {
    return m * n;
});
console.log(result2);

// 案例2--定義常量時, 編寫函數的類型
type myAddFnType = (num1: number, num2: number) => number;
const Add1: myAddFnType = (m, n) => {
    return m + n;
}
console.log(Add1(10, 20));

3. 參數可選類型 

 符號:?

 可選類型需要在必傳參數的后面

function foo(x: number, y?: number) {
    if (y) {
        console.log(x+y);
    } else {
        console.log(x);
    }
}

foo(20, 30)
foo(20)

4. 參數默認值

 從ES6開始,JavaScript是支持默認參數的,TypeScript也是支持默認參數的:

 格式: 直接 = 號 ,寫上默認值就行了

//通常我們寫的順序: 必傳參數 - 有默認值的參數 - 可選參數
function foo(y: number, x: number = 20, z?:number) {
    console.log(x, y)
}

foo(30)

5. 剩余參數

 從ES6開始,JavaScript也支持剩余參數,剩余參數語法允許我們將一個不定數量的參數放到一個數組中。 ts也支持
/* 
    @totalNum: 默認初始值
    @nums:數組
*/
function sum(totalNum: number, ...nums: number[]) {
    let total = totalNum;
    for (const num of nums) {
        total += num;
    }
    return total;
}

console.log(sum(10,100))
console.log(sum(10,100,200))
console.log(sum(10,100,200,300))

6. this的默認推導

// this是可以被推導出來 info對象(TypeScript推導出來)
const info = {
    name: "ypf",
    eating() {
        console.log(this.name + " is eating")
    }
}

info.eating()

7. this的不明確類型

type ThisType = { name: string };

function eating(this: ThisType, message: string) {
  console.log(this.name + " eating", message);
}

const info = {
  name: "why",
  eating: eating,
};

// 隱式綁定
info.eating("哈哈哈");

// 顯示綁定
eating.call({name: "kobe"}, "呵呵呵")
eating.apply({name: "james"}, ["嘿嘿嘿"])

8. 函數重載

 函數的重載: 函數的名稱相同, 但是參數不同的幾個函數, 就是函數的重載
function add(num1: number, num2: number): number; // 沒函數體
function add(num1: string, num2: string): string;
function add(num1: any, num2: any): any {
    if (typeof num1 === 'string' && typeof num2 === 'string') {
        return num1.length + num2.length
    }
    return num1 + num2
}
const result1 = add(20, 30)
const result2 = add("abc", "cba")
console.log(result1)
console.log(result2)

// 在函數的重載中, 實現函數是不能直接被調用的
// add({name: "why"}, {age: 18})


// 實現方式二: 函數的重載
function getLength(args: string): number;
function getLength(args: any[]): number;
function getLength(args: any): number {
    return args.length
}
console.log(getLength("abc"))
console.log(getLength([123, 321, 123]))

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM