TypeScript(四) —— 函數/接口/類/泛型語法總結

目錄

  • 函數類型數組

    • 函數聲明
    • 函數類型表達式
    • 可選參數
    • 任意個數的參數
  • 接口(interface)緩存

    • 定義接口
    • 使用接口
    • 選成員 & 只讀成員 & 動態成員
  • app

    • 須要對類的屬性與方法進行聲明
    • 類成員訪問修飾符(public/private/protected)函數

        1. 定義一個構造函數
        1. 初始化實例對象並訪問構造函數成員
        1. 建立子類繼承構造函數並訪問其成員
    • 類的構造函數被私有化
    • 類的只讀屬性
    • 類與接口post

      • 定義接口
      • 實現接口
    • 抽象類學習

      • 抽象類定義
      • 子類繼承
  • 泛型this

    • 定義泛型參數
    • 調用時傳入泛型參數的類型
  • TypeScript學習地圖

函數類型

函數的輸入和輸出進行約束,及參數和返回值spa

函數聲明

// 參數的類型和返回值的類型
function func1(a: number, b: number): string {
    return 'func1'
}
// 參數類型和個數是固定的,不然報錯
func1(100, 200)

函數類型表達式

// 普通函數
const func4 = function (a: number, b: number): string {
    return 'func2'
}
// 使用箭頭函數
const func5: (a: number, b:number) => string = function(a, b) {
    return 'func2'
}

可選參數

可選參數必定要在必選參數後面,放在函數最後。rest

// 能夠在b後面添加問號表示可選,也能夠直接設置默認值,也能夠不用傳
function func2(a: number, b: number = 10, c?: number): string {
    return 'func1'
}

func1(100)

任意個數的參數

使用ES6rest操做符code

function func3(a: number, b: number = 10, ...rest: number[]): string {
    return 'func1'
}

func1(100,200,300,400)

接口(interface)

接口,是一種規範、契約,約定對象的結構。

接口是用來約束一個對象的結構,咱們要使用這個接口,就要遵循其所有的約定。

接口最直觀的體現就是對象應該有哪些成員以及成員的類型都是什麼樣的?

定義接口

// 定義一個接口,裏面肯定要有兩個成員,且都是字符串類型
interface Post {
  title: string  // 結尾能夠使用逗號分隔,也能夠使用分號去分割,還能夠省略
  content: string
}

使用接口

// 使用的時候聲明參數是Post類型,裏面使用的時候不擔憂沒有值
function printPost (post: Post) {
  console.log(post.title)
  console.log(post.content)
}

// title和content任何一個沒有傳或者不是字符串都會報錯
printPost({
  title: 'this is a title',
  content:'this is a content'
})

可選成員 & 只讀成員 & 動態成員

  • 可選成員 : 定義接口的時候添加問號,傳參的時候無關緊要
interface Post {
  title: string
  content: string
  subtitle?: string // 可選成員,無關緊要,string or undefined
}

// 下面不傳subtitle不會報錯
const hello: Post = {
    title: 'this is a title',
    content:'this is a content'
}
  • 只讀成員 :定義接口的時候前面添加readonly關鍵詞,一經定義不能修改
interface Post {
  title: string
  content: string
  subtitle?: string
  readonly summary: string //只讀成員,一經定義不能更改
}

const hello: Post = {
    title: 'this is a title',
    content:'this is a content',
    summary: 'this is a summary'
}

hello.summary = 'hello' // 報錯
  • 動態成員 :不肯定有哪些成員,本身定義添加,通常這種都存在動態對象裏面,例如程序中的緩存對象。

由於不知道有哪些成員名稱,因此Cache裏面使用[],指定鍵prop的類型是string,值的類型是number

interface Cache {
  [prop: string] : number
}

const cache: Cache = {}

cache['hello'] = 1
cache['hi'] = 2

類用來描述一類具體事物的抽象特徵。TypeScript加強了class的相關語法,訪問修飾符以及抽象類的概念等...

下面看一下TypeScript新增的內容:

須要對類的屬性與方法進行聲明

目的是爲了給屬性和方法作類型標註

class Person {
  // 須要對類的屬性進行聲明,能夠添加默認值,也能夠不添加
  // 二者有一個沒有寫,都會報錯
  name: string = 'init name'
  age: number
  
  constructor (name: string, age: number) {
    // 若是不加聲明,這裏直接使用會報錯,由於在TypeScipt須要明確屬性,而不是動態添加
    this.name = name
    this.age = age
  }
  
  // 方法這些和以前是同樣的,也要添加類型註解
  sayHi (msg: string): void {
    console.log(`I am ${this.name}, ${msg}`)
  }

  run (): void {
    this.sayHi('I am happy!')
  }
}

類成員訪問修飾符(public/private/protected)

- public private protected
內部訪問
外部訪問 不可 不可
子類訪問 不可
1. 定義一個構造函數
class Person {
  // 默認是public,加不加效果同樣,建議去加
  public name: string = 'init name'
  // age屬性是個私有屬性,私有屬性能夠在函數內部經過this.age去訪問
  private age: number
  // 受保護的,外界成員不可訪問,子類成員能夠訪問
  protected gender: boolean

  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }

  sayHi (msg: string): void {
    console.log(`I am ${this.name}, ${msg}`)
    console.log(this.age) //本身內部訪問私有屬性是沒有問題的
    console.log(this.gender) //本身內部訪問受保護屬性是沒有問題的
  }
}
2. 初始化實例對象並訪問構造函數成員
const xm = new Person('xm', 18)
console.log(xm.name)
console.log(xm.age) // 報錯,Property 'age' is private and only accessible within class 'Person'
console.log(xm.gender) // 報錯,Property 'gender' is protected and only accessible within class 'Person' and its subclasses.
3. 建立子類繼承構造函數並訪問其成員
//定義一個Student類繼承Person
class Student extends Person {
  constructor(name: string, age: number) {
    super(name, age)
    console.log(this.gender)
    console.log(this.age) // 報錯,私有成員不能訪問
    console.log(this.name)
  }
}

類的構造函數被私有化

  • private: 若是類的構造函數被私有化,那麼不能被實例化和繼承,這個時候只能在這個類的內部添加一個靜態方法,經過靜態方法添加實例。
  • protected: 若是類的構造函數被受保護,那麼不能實例化,可是能夠繼承。
class Student extends Person {
  private constructor(name: string, age: number) {
    super(name, age)
    console.log(this.gender)
    console.log(this.name)
  }
  // 能夠定義一個方法內部實例化
  static create (name: string, age: number) {
    return new Student(name, age)
  }
}

const xm = Student.create('xm', 18)
console.log(xm.name)

類的只讀屬性

在屬性前添加修飾符readonly,若是有訪問修飾符,那麼就跟在修飾符的後面.只讀屬性必須在聲明時或構造函數裏被初始化。

class Person {
  public name: string = 'init name'
  private age: number
  // 若是有訪問修飾符,那麼就跟在修飾符的後面
  protected readonly gender: boolean

  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }

  sayHi (msg: string): void {
    console.log(`I am ${this.name}, ${msg}`)
    console.log(this.gender = false) // Cannot assign to 'gender' because it is a read-only property.
  }

  run (): void {
    this.sayHi('I am happy!')
  }
}

let xm = new Person('xm', 18)
xm.gender = 'false' // 報錯

類與接口

類與類之間的公共特徵通常會用接口去抽象

好比下面兩個不一樣的類,可是都有eatrun兩個相同的方法,能夠用接口約束兩個類中公共的部分

class Person {
  eat (food: string): void {
    console.log(`優雅進餐:${food}`)
  }

  run (distance: number) {
    console.log(`直立行走:${distance}`)
  }
}

class Animal {
  eat (food: string): void {
    console.log(`不優雅進餐:${food}`)
  }

  run(distance: number) {
    console.log(`爬行:${distance}`)
  }
}
定義接口
// 能夠定義一個接口實現一個能力,而後讓一個類實現多個接口

interface Eat {
  eat (food: string): void
}

interface Run {
  run (distance: number): void
}
實現接口
// Person和Animal要實現接口,若是裏面少了接口對應的方法,就會報錯。
class Person implements Eat, Run{
  eat (food: string): void {
    console.log(`優雅進餐:${food}`)
  }

  run (distance: number) {
    console.log(`直立行走:${distance}`)
  }
}

class Animal implements Eat, Run{
  eat (food: string): void {
    console.log(`不優雅進餐:${food}`)
  }

  run(distance: number) {
    console.log(`爬行:${distance}`)
  }
}

抽象類

  • 抽象類與接口有些相似,也是約束子類中必需要有哪些成員,不一樣的是抽象類裏面能夠包含一些具體的實現
  • 抽象類只能繼承,不能實例化對象
  • 抽象類中能夠定義一些抽象方法
  • 抽象方法不須要方法體,當父類中有抽象方法的時候,子類必需要實現抽象方法
抽象類定義
// 添加abstract關鍵詞以後就成爲了抽象類
abstract class Animal {
  eat (food: string): void {
    console.log(`不優雅進餐:${food}`)
  }
  // 抽象類中能夠定義一些抽象方法,也須要關鍵詞abstract
  abstract run (distance: number): void
}
子類繼承
class Dog extends Animal {
  // 能夠在VSCode環境點擊Dog使用快速修復自動生成代碼實現
  // 這裏實現了抽象類中的run抽象方法
  run(distance: number): void {
    console.log('爬行', distance)
  }
}

// 子類實例化
const d = new Dog()
d.eat('糧食')
d.run(100)

泛型

咱們在定義函數、接口或者類的時候沒有去指定類型,只有當使用的時候纔去指定類型的一種特徵。

其目的 就是爲了極大程度複用咱們的代碼

舉個例子:

下面是傳入長度和值,返回一個數組

// 參數長度是number類型,value是number類型,返回的是number類型的數組
function createArray (length: number, value: number): number[] {
  const arr = Array<number>(length).fill(value)
  return arr
}

// 下面傳入參數能夠得到三個值爲100的數字類型的數組
const res = createArray(3, 100) // res => [100, 100, 100]

上面的代碼有個缺陷是隻能返回數字類型的數組,若是換成其餘類型就會報錯,如何進行修改?

定義泛型參數

  • 函數名後面使用尖括號,裏面定義泛型參數
  • 通常泛型參數都用大寫的T做爲名稱,函數中不明確的類型都用T去表明
function createArray <T> (length: number, value: T): T[] {
  const arr = Array<T>(length).fill(value)
  return arr
}

調用時傳入泛型參數的類型

  • 調用時在函數名後面用尖括號內部填入參數的類型
// 下面能夠填充字符串類型或者數字類型均可以
const res = createArray<string>(3, 'foo')
const res1 = createArray<number>(3, 100)

總結 就是泛型參數將定義時不能明確的參數用一個T來代替,使用的時候指定T的類型

TypeScript學習地圖

相關文章
相關標籤/搜索