2020-1-31-Typescript基礎知識

SylvesterZhang發表於2024-03-22

typescript安裝、編譯、資料型別、函式宣告、ES5中的類、TS中的類、介面、泛型、裝飾器

Typescript安裝

npm installl -g typescript

編譯成js

tsc aaa.ts

執行該命令後會自動生成js檔案


在VScode中設定儲存後自動編譯

1.生成tscconfig.json檔案

tsc --init

2.修改tscconfig.json檔案中outDir:'/js',此後生成的js檔案會存入js的資料夾中

3.VScode編輯器裡

任務-執行任務,點選監視tsconfig.json


資料型別

1.布林型別 boolean

2.數字型別 number

3.字串型別 string

4.陣列型別 array

let ar:number[]=[1,2,3]

5.元組型別 tuple

let ar:[string,number,number]=["1",2,3]

實際上就是一個允許不同資料型別的陣列

6.列舉型別 enum

enum color {red,green,blue}
let c:color=color.green
console.log(c)//1

7.任意型別 any

window.onload=function(){
    let box:any=document.getElementById("div")//獲取元素時,元素物件型別為any
    box.innerHTML="hello"
}

8.null和undefined

var num:number//num未進行初始化,編譯報錯
console.log(num)

var num:number|null|undefined//num如果未初始化,賦值為null或undefined
console.log(num)

9.void型別

function run():void{//該方法無返回值
	console.log("run")
}

10.never型別

哪些永遠不存在的值的型別,返回never的函式必須存在無法達到的終點

//這是官方文件的例子
// 返回never的函式必須存在無法達到的終點
function error(message: string): never {
    throw new Error(message);
}

// 推斷的返回值型別為never
function fail() {
    return error("Something failed");//會丟擲錯誤
}

// 返回never的函式必須存在無法達到的終點
function infiniteLoop(): never {
    while (true) {
    }
}

函式宣告

1.普通方式和匿名函式方式宣告

//普通方式
function run():void{
	console.log("run")
}
run()//輸出run

//匿名函式方式
var run1=function():void{
	console.log("run")
}
run1()//輸出run

2.引數、可選引數、預設引數

//引數
function getinfo(name:string,age:number):string{
    return `${name}--${age}`
}
console.log(getinfo("aaa",25))//輸出aaa--25

//可選引數,必須配置到引數的最後面
function getinfo1(name:string,age?:number):string{
    return `${name}--${age}`
}
console.log(getinfo1("aaa"))//輸出aaa--undefined

//預設引數
function getinfo2(name:string,age:number=20):string{
    return `${name}--${age}`
}
console.log(getinfo2("aaa"))//輸出aaa--20

可選引數這裡和js完全不同,如果時可選引數必須用“?”標記出來,否則會報錯。而在js中不傳第二個引數時不會報錯,第二個引數會預設為undefined。

3.剩餘引數,“...”接收傳過來的所有引數

function sum(...result:number[]):number{
    var sum=0
    for(var i=0;i<result.length;i++){
        sum+=result[i]
    }
    return sum
}
console.log(sum(1,2,3,4))//輸出 10

4.解構用於函式宣告

type C = { a: string, b?: number }
function f({ a, b }: C): void {
    console.log("a:",a,"b:",b)
}
f({a:"qwe"})//輸出 a: qwe b: undefined

5.方法過載

function getInfo(name:string):string
function getInfo(name:string,age:number):string

function getInfo(name:string,age?:any):any{
    if(age){
        return "我叫:"+name+"我的年齡是:"+age
    }else{
        return "我叫:"+name
    }
}
console.log(getInfo("zhang"))//輸出 我叫:zhang
console.log(getInfo("zhang",18))//輸出  我叫:zhang我的年齡是:18
//console.log(getInfo(123)) 這樣寫是錯誤的

ES5中類

1.定義

function person(name,age){
            this.name=name
            this.age=age
            this.run=function(){
                console.log(this.name+'在運動')
            }
        }
        person.getinfo=function(){
            console.log("我是靜態方法")
        }//定義靜態方法

        //原型鏈上定義屬性、方法
            
        person.prototype.sex="男"//原型鏈上屬性會被多個例項共享
        person.prototype.work=function(){
            console.log(this.name+"在工作")
        }

        person.getinfo()//執行靜態方法,輸出	我是靜態方法

        p=new person("zhang",18)
        p.run()//執行物件方法,輸出	zhang在運動
        p.work()//執行原型鏈方法,輸出	zhang在工作

2.繼承

1)物件冒充實現繼承

function web(name,age){
	person.call(this,name,age)//物件冒充實現繼承
}
var w=new web("zhang",18)
w.run()//輸出	zhang在運動
w.work()//報錯,物件不支援work屬性或方法

只可繼承建構函式里的屬性和方法,無法繼承原型鏈裡的屬性和方法

2)原型鏈實現繼承

function web(name,age){
            
}
web.prototype=new person("zhang",18)
var w=new web()
w.run()//輸出	zhang在運動
w.work()//輸出	zhang在工作

既可繼承建構函式里的屬性和方法,又可以繼承原型鏈裡的屬性和方法。問題也很明顯,例項化時子類無法給父類傳參

3)物件冒充組合原型鏈實現繼承

function web(name,age){
	person.call(this,name,age)
}
web.prototype=person.prototype
var w=new web("zhang",18)
w.run()//輸出	zhang在運動
w.work()//輸出	zhang在工作

既可繼承建構函式里的屬性和方法,又可以繼承原型鏈裡的屬性和方法,解決原型鏈繼承中的問題


TS中的類

1類的定義

class person{
    name:string
    constructor(name:string){
        this.name=name
    }
    run():void{
        console.log(`${this.name}在跑步`)
    }
}

var p=new person('zhang')
p.run()//輸出	zhang在跑步

2類的繼承

class worker extends person{
    constructor(name:string){
        super(name)
    }
    work():void{
        console.log(`${this.name}在工作`)
    }
}

var w=new worker('huan')
w.run()//輸出	huan在跑步
w.work()//輸出	huan在工作

3類的修飾符

public 公有,在類、子類裡外都可訪問

protected 保護型,在類、子類裡可訪問,在類外不可訪問

private 私有型,在類裡可訪問,字類裡、外都不可訪問

4抽象類

abstract class animal{
    public name:string
    constructor(name:string){
        this.name=name
    }
    abstract eat():any//定義抽象方法,其字類必須實現該方法
}

class dog extends animal{
    constructor(name:string){
        super(name)
    }
    eat():any{
        console.log(`${this.name}在吃狗糧`)
    }
}

var d=new dog('小黑')
d.eat()//輸出	小黑在吃狗糧

介面

為達到規範,定義的一種約束

1.約束

//對函式引數的約束
interface config{
    type:string;
    url:string;
    data?:string;
    dataType:string;
}
function ajax(config:config){
    var xhr=new XMLHttpRequest()
    xhr.open(config.type,config.url,true)
    xhr.send(config.data)
    xhr.onreadystatechange=function(){
        if(xhr.readyState==4&&xhr.status==200){
            console.log("success")
            if(config.dataType=='json'){
                console.log(JSON.parse(xhr.responseText))
            }else{
                console.log(xhr.responseText)
            }
        }
    }
}

ajax({
    type:'get',
    data:'name=zhang',
    url:'http://a.itying.com/api/productlist',
    dataType:'json'
})

//對函式的約束
interface encrypt{
    (key:string,value:string):string
}

var md5:encrypt=function(key:string,value:string):string{
    return key+value
}

console.log(md5('zhang','huan'))

//對陣列的約束
interface userarr{
    [index:number]:string
}
var arr:userarr=['aaa','bbb']
console.log(arr[0])

//對物件的約束
interface userobj{
    [index:string]:string
}
var obj:userobj={
    name:'zhang'
}
console.log(obj.name)

//對類的約束
interface animal{
    name:string
    eat(str:string):void
}
class dog implements animal{
    name:string
    constructor(name:string){
        this.name=name
    }
    eat(){
        console.log(`${this.name}吃狗糧`)
    }
}
var xiaohei=new dog("小黑")
xiaohei.eat()

class cat implements animal{
    name:string
    constructor(name:string){
        this.name=name
    }
    eat(food:string){
        console.log(`${this.name}吃${food}`)
    }
}
var xiaohua=new cat("小花")
xiaohua.eat("耗子")

2繼承

//官方文件的多繼承例子
interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = <Square>{};//例項化一個物件
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

泛型

在定義函式、介面或類的時候,不預先設定其型別,而在呼叫時在指定型別

function go<T>(arg:T):T{
    console.log(arg)
    return arg
}
go('go,go,go……')//輸出	gp,go,go……

裝飾器

1修改tsconfig.json檔案,使得VS支援裝飾器功能

"experimentalDecorators": true,

2使用

//類裝飾器
function logclass(params:any) {//params就是當前類
    params.prototype.apiurl="動態擴充套件屬性"//給類擴充套件屬性
    params.prototype.run=function(){//給類擴充套件方法
        console.log("這是擴充套件的run方法")
    }
}

@logclass
class httpclient{

}

var h:any=new httpclient()
console.log(h.apiurl)//輸出	動態擴充套件屬性
h.run()//輸出	這是擴充套件的run方法

//裝飾器工廠
function logclass(params:any) {//外部引數
    return function(target:any){//target是當前類
        console.log(params)
        console.log(target)
    }
}

@logclass("hello")//可傳參
class httpclient{

}

var h=new httpclient()
//輸出  hello
//輸出  f httpclient() {
//    }

//裝飾器修改類的建構函式
function logclass(params:any):any {
    return class extends params{
        constructor(){
            super(name)
            this.name="修改後的建構函式"
            console.log(this.name)
        }
    }
}

@logclass//可傳參
class httpclient{
    name:string|undefined
    constructor(){
        this.name="修改前的建構函式"
        console.log(this.name)
    }
}

var h=new httpclient()
//輸出  修改前的建構函式
//輸出  修改後的建構函式

//屬性裝飾器
function logproperty(params:any){//params外部引數
    return function(target:any,attr:any){//target是原型物件,attr是物件的屬性,這裡會將修飾的屬性自動傳入
        console.log(target)
        console.log(attr)
        target[attr]=params
    }
}

class httpclient{
    @logproperty("xxx.com")
    name:string|undefined
    constructor(){
    }
}

var h=new httpclient()
console.log(h.name)
//輸出  {constructor: ƒ}
//輸出  name
//輸出  xxx.com

//方法裝飾器
//傳入3個引數分別接收:類的原型物件、成員名字、成員屬性描述符
function get(params:any):any {
    return function(target:any,methodname:any,desc:any){
        console.log(target)
        console.log(methodname)
        console.log(desc)
    }
}


class httpclient{
    name:string|undefined
    constructor(){
        this.name="zhanghuan.top"
        console.log(this.name)
    }
    @get("abcdefg")//放在方法上
    getdata(){
        console.log(this.name)
    }
}

var h=new httpclient()
//輸出  {getdata: ƒ, constructor: ƒ}
//輸出  getdata
//輸出  {value: ƒ, writable: true, enumerable: true, configurable: true}
//輸出  zhanghuan.top

3裝飾器執行順序

屬性>方法>方法引數>類