函數類型數組
接口(interface)緩存
類app
類成員訪問修飾符(public/private/protected)函數
類與接口post
抽象類學習
泛型this
函數的輸入和輸出進行約束,及參數和返回值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)
使用ES6
的rest
操做符code
function func3(a: number, b: number = 10, ...rest: number[]): string { return 'func1' } func1(100,200,300,400)
接口,是一種規範、契約,約定對象的結構。
接口是用來約束一個對象的結構,咱們要使用這個接口,就要遵循其所有的約定。
接口最直觀的體現就是對象應該有哪些成員以及成員的類型都是什麼樣的?
// 定義一個接口,裏面肯定要有兩個成員,且都是字符串類型 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 |
---|---|---|---|
內部訪問 | 可 | 可 | 可 |
外部訪問 | 可 | 不可 | 不可 |
子類訪問 | 可 | 不可 | 可 |
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) //本身內部訪問受保護屬性是沒有問題的 } }
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.
//定義一個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' // 報錯
類與類之間的公共特徵通常會用接口去抽象
好比下面兩個不一樣的類,可是都有eat
和run
兩個相同的方法,能夠用接口約束兩個類中公共的部分
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
的類型