1. 編程語(yǔ)言的類型 : 動(dòng)態(tài)類型語(yǔ)言 和 靜態(tài)類型語(yǔ)言(c\ C++ \Jave)
2. Typescript 是什么 尘吗?
1. 是通過(guò)在JavaScrip的基礎(chǔ)上添加了靜態(tài)類型風(fēng)格的類型系統(tǒng)
2. 對(duì)es6到es10的預(yù)發(fā)支持,兼容各種瀏覽器
3. 為什么要使用Typescript
優(yōu)點(diǎn):
- 程序容易理解 定義函數(shù)或者方法輸入輸出的參數(shù)類型可容易理解程序
- 效率更高 ,通過(guò)ide代碼可自動(dòng)補(bǔ)全榜贴、自動(dòng)識(shí)別錯(cuò)誤信息
- 包容性好 , 完全兼容JavaScript
缺點(diǎn): - 學(xué)習(xí)成本高
- 短期增加了一些開(kāi)發(fā)成本
4. 安裝typescript
node版本12.5.0 ,建議 10以上, npm 版本6.9.0 浙踢,tsc 版本3.8.3
ts-node XXX.ts 執(zhí)行ts,輸出結(jié)果
tsc XXX.ts 編譯ts為js文件
5. Typescript數(shù)據(jù)類型
原始數(shù)據(jù)類型 string灿渴、boolean洛波、number、undefined 骚露、null
注意 undefined 和 null 是所有類型的子類型蹬挤,可以隨意賦值給其它數(shù)據(jù)類型。
let flag :boolean = true
let issure: any = 123 // 不確定數(shù)據(jù)類型用法
issure = "abc"
復(fù)雜數(shù)據(jù)類型 數(shù)組array 和元組 tuple
let arr1: number[] = [12, 2, 34]
let arr2: [number, string] = [123, 'abc']
interface接口 針對(duì)object進(jìn)行約束
interface IPerson {
readonly id : number; //readonly 只讀不可編輯
age ? : number, // 荸百? IPerson age屬性可有可無(wú)
name : string
}
let na : IPerson = {
id:1,
age : 2 ,
name: 'nana'
}
interface接口 針對(duì)數(shù)組對(duì)象進(jìn)行約束
class Data {
[propName: string]: any
}
interface Ret {
code: number,
data: Array<Data>,
message: String
}
const ret: Ret = {
code: 200,
data: [{ id: 1 }],
message: '錯(cuò)誤信息'
}
console.log(ret.data[0].name)
interface接口 針對(duì)function輸入輸出約束
interface ISum {
(x:number,y:number,z ?: number) :number
}
let add :ISum = (x:number,y:number,z ?:number):number => {
if( typeof z === 'number'){
return x + y + z
}else{
return x + y
}
}
add(1,2,3)
6. 類型推斷 聯(lián)合類型 類型斷言
let num = 123闻伶; // num 此時(shí)類型被推斷為 number類型,不可修改為其他類型
//聯(lián)合類型 union types : 不確定一個(gè)類型的變量到底是哪個(gè)類型的時(shí)候 够话,只需要用中豎線來(lái)分割兩個(gè)類型,此時(shí)只能訪問(wèn)此聯(lián)合類型的所有類型里共有的屬性或方法:
let numberOrstring: number | string;
numberOrstring = 123;
numberOrstring = 'abc';
//類型斷言 可以用 as 關(guān)鍵字光绕,告訴typescript 編譯器參數(shù)女嘲。
function getLength(input : number | string) :number {
const inp = input as string;
if(inp.length){
return inp.length
}else{
const num = input as number;
return num.toString().length
}
}
7. Class 類
在JavaScript 使用構(gòu)造函數(shù) 原型鏈實(shí)現(xiàn)繼承;
Es6出現(xiàn)Class概念诞帐,內(nèi)部使用原型鏈機(jī)制實(shí)現(xiàn) 欣尼,有了面向?qū)ο蟮母拍睿?br>
面向?qū)ο蠡拘g(shù)語(yǔ):
- 類(class) :定義了一切事物的抽象特點(diǎn)
- 對(duì)象 (Object) : 類的實(shí)例,通過(guò)New生成
- 面向?qū)ο?(OOP) 三大特性:封裝 停蕉、繼承愕鼓、多態(tài)
封裝: 將數(shù)據(jù)操作細(xì)節(jié)隱藏起來(lái),對(duì)外只暴露接口慧起,只通過(guò)接口訪問(wèn)該對(duì)象菇晃。 創(chuàng)建一個(gè)Animal類
class Animal {
constructor(name){
this.name = name;
}
run(){
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run())
繼承: 子類可以繼承父類的特征 。通過(guò)extends繼承
class Dog extends Animal{
eat(){
return `${this.name} is eatting`
}
}
const kele = new Dog('kele')
console.log(kele.run())
console.log(kele.eat())
多態(tài): 通過(guò)繼承蚓挤,子類也可以擁有自己的方法磺送。
class Cat extends Animal{
static cate = ['cateqqq'] //靜態(tài)屬性、方法灿意,與實(shí)例沒(méi)有太大的關(guān)系
construcor(name){
super(name) //重寫(xiě)構(gòu)造函數(shù)需要使用super方法
}
run(){
return 'Hi,' + super.run() //調(diào)用父類方法需要使用 super關(guān)鍵字
}
}
const maomao = new Cat('maomao')
console.log(maomao.run())
console.log(Cat.cate )
Typescript中的class
3種訪問(wèn)修飾符 估灿,類上的屬性和方法添加權(quán)限管理
- Public :修飾的屬性和方法是共有的,可以在任何地方被調(diào)用到缤剧,默認(rèn)使用的
class Animal {
name: string;
constructor(name) {
this.name = name;
}
run() {
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run())
- private : 修飾的屬性和方法是私有的馅袁,子類也不可以訪問(wèn)和修改
class Animal {
name: string;
constructor(name) {
this.name = name;
}
private run() {
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run()) //報(bào)錯(cuò) 屬性'run'為私有屬性,只能在類'Animal '中訪問(wèn)
- Protected: 修飾的屬性和方法是受保護(hù)的荒辕,子類可以訪問(wèn)
- readonly : 只能讀 不可以寫(xiě)
class Animal {
readonly name: string;
constructor(name) {
this.name = name;
}
protected run() {
return `${this.name} is running`
}
}
class Cat extends Animal {
construcor(name) {
super(name) //重寫(xiě)構(gòu)造函數(shù)需要使用super方法
}
run() {
return 'Hi,' + super.run() //調(diào)用父類方法需要使用 super關(guān)鍵字
}
}
const maomao = new Cat('maomao')
console.log(maomao.run())
8. 類和接口 搭檔使用
interface 用于對(duì)對(duì)象的形狀進(jìn)行描述汗销,描述函數(shù)的類型芒粹,對(duì)類的一部分形為進(jìn)行抽象。
- 繼承困境 : 一個(gè)類只能繼承自另外一個(gè)類大溜,不同類之間需要有共同的特性化漆,使用子類調(diào)用父類的方法不太合適。
- 特性提取成接口钦奋,用一個(gè) implements關(guān)鍵字來(lái)實(shí)現(xiàn)接口蹬耘,提高面向?qū)ο蟮撵`活性。
//特性1 :收音機(jī)
interface Radio {
switchRadio(trigger: boolean): void //void關(guān)鍵字代表什么也不返回
}
//特性2 :檢查電池容量
interface Checkbox {
checkBoxStatus(): void
}
//特性3 : 接口之間的繼承 RadioWithCheckbox 接口繼承Radio 枫浙,即有開(kāi)關(guān)收音機(jī)又有檢查電池容量
interface RadioWithCheckbox extends Radio {
checkBoxStatus(): void
}
class Car implements Radio {
switchRadio(trigger: boolean) {
}
}
//可寫(xiě)為 class Mobile implements Radio 我磁,Checkbox ,也可以寫(xiě)為 :
class Mobile implements RadioWithCheckbox {
switchRadio(trigger: boolean) {
}
checkBoxStatus() {
}
}
9. 枚舉 enums
枚舉: 指的是常量情況厌衔,執(zhí)行程序不會(huì)改變 璧帝,在js中用const , 取值在一定范圍內(nèi)的一系列常量富寿,例 一周7天睬隶; 這種情況需要用枚舉表示
//數(shù)字枚舉
enum Direction {
Up, //0 Up也可手動(dòng)賦值 10, 下面會(huì)自動(dòng)遞增 Up = 10
Down, //1
Left, //2
Right //3
}
console.log(Direction.Up) //返回0
console.log(Direction[0]) //返回Up
//字符串枚舉 页徐,提升性能 編譯代碼簡(jiǎn)單
enum DirectionS {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
const value = 'UP'
if (value === DirectionS.Up) {
console.log('go up!')
}
10. 泛型 Generics
泛型 指定義函數(shù) 接口或 類的時(shí)候不予先指定具體類型苏潜,而是在使用的時(shí)候在指定類型的一種特征
//泛型定義進(jìn)階1
function echo(arg) {
return arg
}
const result = echo(123) //發(fā)現(xiàn)返回結(jié)果為any類型,變量喪失了類型
//泛型定義進(jìn)階2
function echo1(arg: number): number {
return arg
}
const result1 = echo1(123) // echo1返回number類型变勇,但需求有可能傳入各種類型恤左,滿足不了需求
//泛型定義進(jìn)階3
function echo2(arg: any): any {
return arg
}
const result2: string = echo2(123) //喪失類型,返回any類型搀绣,還存在一個(gè)問(wèn)題飞袋,傳入和返回的值無(wú)法做到統(tǒng)一,返回any類型链患,傳入的string類型 屬于any下的類型
//泛型使用generics 占位符傳入1個(gè)參數(shù)
function echo3<T>(arg: T): T {
return arg
}
const result3 = echo3(123) //傳入數(shù)字123巧鸭,通過(guò)類型推斷,返回?cái)?shù)字類型
//泛型使用generics 占位符傳入元組
function swap<T, U>(tuple: [T, U]): [T, U] {
return (tuple[0], tuple[1])
}
const result4 = swap(['string', 123])
約束泛型
// 泛型約束進(jìn)階1
function echoWithArr<T>(arg: T): T {
console.log(arg.length) //報(bào)錯(cuò)锣险,類型T上不存在length屬性蹄皱,所以得對(duì)泛型做約束
return arg;
}
//泛型約束進(jìn)階2
function echoWithArr1<T>(arg: T[]): T[] {
console.log(arg.length)
return arg;
}
const arrs = echoWithArr1([1, 2, 3]) //返回正確的number數(shù)組,處理并不完美芯肤, string和對(duì)象都可能有l(wèi)ength屬性
// const str = echoWithArr1('str') //返回報(bào)錯(cuò)巷折,string類型參數(shù)不能賦值給元組[]類型
//進(jìn)行約束,只允許這個(gè)函數(shù)傳入包含length屬性的變量,新建一個(gè)interface ,包含length屬性
interface Iwithlength {
length: number
}
//使用extends關(guān)鍵字約束傳入的泛型,只返回傳入的參數(shù)有l(wèi)ength屬性
function echoWithLength<T extends Iwithlength>(arg: T): T {
console.log(arg.length)
return arg
}
const str1 = echoWithLength('str')
const obj1 = echoWithLength({ length: 10 })
const arrs2 = echoWithLength([1, 2, 3, 4])
const num = echoWithLength(10) //錯(cuò)誤崖咨,類型number的參數(shù)不能賦值給Iwithlength的參數(shù)
類泛型約束
// 類泛型進(jìn)階1
class Queue {
private data = [];
push(item) {
return this.data.push(item)
}
pop() {
return this.data.shift()
}
}
const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pop().toFixed()) //刪除第一個(gè)元素并返回1 锻拘,數(shù)字1可以使用toFixed方法
console.log(queue.pop().toFixed()) //ts不報(bào)錯(cuò),但是編譯js后會(huì)報(bào)錯(cuò), string類型不可以使用toFixed方法
//類泛型約束 解決上訴問(wèn)題 署拟,無(wú)論什么類型被推入隊(duì)列 婉宰, 推出的類型和推入類型一致
class Queue1<T>{
private data = [];
push(item: T) {
return this.data.push(item)
}
pop(): T {
return this.data.shift()
}
}
const queue1 = new Queue1<number>()
queue1.push(1)
queue1.push('sre') //報(bào)錯(cuò)類型string的參數(shù)不能賦值給類型number的參數(shù)
console.log(queue1.pop().toFixed())
泛型在interface的應(yīng)用
interface Keypair<T, U> {
key: T
value: U
} //key,value 的值動(dòng)態(tài)傳入
let kp1: Keypair<number, string> = { key: 1, value: 'str' }
let kp2: Keypair<string, number> = { key: 'str', value: 1 }
let kp3: Keypair<string, number> = { key: 1, value: 2 } //報(bào)錯(cuò) 不能將key的類型number傳入 string類型
泛型表示number數(shù)組類型
let arr1: number[] = [12, 2, 34]
let arr2: Array<number> = [1, 2, 3]
11.類型別名、字面量 推穷、交叉類型
- 類型別名type-aliase
let sum: (x: number, y: number) => number
const result = sum(1, 2)
//每次寫(xiě)入繁雜心包,可使用type關(guān)鍵字創(chuàng)建類型別名
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)
//也可使用type創(chuàng)建聯(lián)合類型
type StrOrNum = string | number
let result3: StrOrNum = 'abc'
result3 = 124
- 字符串 字面量 ,可以提供非常方便的一系列常量寫(xiě)法
const str: 'name' = 'name'
const number: 2 = 2
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Left'
- 交叉類型
interface IName {
name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: 'a', age: 27 }
12.聲明文件
使用第三方庫(kù)的時(shí)候馒铃,第三方庫(kù)不是通過(guò)typescript寫(xiě)的 ,直接使用jQuery('#foo')報(bào)錯(cuò)蟹腾,需要通過(guò)declare var 聲明
declare var jQuery: (selector:string) = > any ;
//聲明語(yǔ)句,僅僅全局定義jquery的類型区宇,編譯時(shí)的檢查娃殖,最簡(jiǎn)單的聲明文件寫(xiě)法
jquery.d.ts //聲明語(yǔ)句放到聲明文件中
使用第三庫(kù)的typescript社區(qū) :,可直接安裝它的類型文件
[社區(qū)地址] (https://www.typescriptlang.org/dt/search?search=)
13.內(nèi)置類型
在ts中可以隨意使用最新的JavaScript語(yǔ)法
- 默認(rèn)內(nèi)置類型
//global objects
const arr: Array<number> = [12, 23, 3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('as')
Math.pow(1, 2)
//Dom and Bom
let body = document.body;
let allLis = document.querySelectorAll('li')
allLis.length
document.addEventListener('click', (e) => {
e.preventDefault()
})
- typescript 提供內(nèi)置類型
具體文檔 https://www.typescriptlang.org/docs/handbook/utility-types.html ,例子:
//Partial 把傳入的類型可變成可選
interface Iperson {
name: string
age: number
}
let viking: Iperson = { name: 'na', age: 12 }
type Ipartial = Partial<Iperson> // Iperson的參數(shù)都變?yōu)榭蛇x參數(shù)
let viking2: Ipartial = {}
// Omit 可以忽略傳入的某個(gè)屬性
type Iomit = Omit<Iperson, 'name'> //忽略name屬性
let viking3: Ipartial = { age: 12 }