1. 程式人生 > 實用技巧 >TypeScript學習

TypeScript學習

TypeScript

1.微軟開發的開源的組合語言

示列

function greeter(ts :string) {
    return "hellow"+ts;
}
var test = "a";
let user = "Jane User";

document.body.innerHTML = greeter(user);
:string 表示的是型別註解

介面

interface person{
    lastName:String;
    firstName:String;
}
function greeter(person:person) {
    return "hello"+person.firstName+" "+person.lastName;
}
let user = { firstName:"Jane",lastName:"User"}
document.body.innerHTML = greeter(user);

class Student {
    fullName: string;
    constructor(public firstName: string, public middleInitial: string, public lastName: string) {
        this.fullName = firstName + " " + middleInitial + " " + lastName;
    }
}

interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person: Person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}

let user = new Student("Jane", "M.", "User");

document.body.innerHTML = greeter(user);
TypeScript基本資料型別
  1. 布林值

    let isDone: boolean = false;
    
  2. 數字

    let decLiteral: number = 6;
    let hexLiteral: number = 0xf00d;
    let binaryLiteral: number = 0b1010;
    let octalLiteral: number = 0o744;
    
  3. 字串 模板字串 ${}

    let name: string = "bob";
    name = "smith";
    
  4. 陣列

    let list: number[] = [1, 2, 3];
    
  5. 元祖 Tuple

    元祖相當於混個多種型別

    // Declare a tuple type
    let x: [string, number];
    // Initialize it
    x = ['hello', 10]; // OK
    // Initialize it incorrectly
    x = [10, 'hello']; // Error
    
  6. 列舉

  7. 任意值

    對於一些現在還不算清楚的變數指定一個型別我們會採取任意型別

    let notSure: any = 4;
    notSure = "maybe a string instead";
    notSure = false; // okay, definitely a boolean
    
  8. 空值

  9. Null和Undefined

    是所有型別的子型別

  10. Never

    表示那些永不存在的值的型別

  11. Object

    代表的是非原始型別,也就是除了numberstringbooleansymbolnullundefined之外的型別。

使用方法

  1. tsc --init
ES5定義函式的方法
//普通函式的申明
function run() {
	return "run"
}
//匿名函式宣告
var run2 = function() {
	return "run"
}
ts中定義函式的方法

如果有返回值

//函式宣告需要返回宣告
function run():string{
return "run";
}
//匿名函式法
var fun2 = function():number{
	return 123;
} 

//ts中定義方法傳參

函式宣告

function getInfo(name:string.age:number):string{
	return `${name} ----- ${age}`;
}

匿名函式

var getInfo = function(name:string.age:number):string{
	return `${name} ----- ${age}`;
}

//沒有返回值的方法

function run():void{
return "age";
}

方法可選引數

function run(name:string,age?:number){
    if(age){
        return `${age}`;
    }else{
        return `${name}`;
    }
}
?的意思是可選引數相當於可以傳入引數也可以不傳入引數

//可選引數必須到引數的最後面

預設引數

es5裡面沒法設定預設引數。es6和ts可以設定

function run(name:string,age:number =20){
    if(age){
        return `${age}`;
    }else{
        return `${name}`;
    }
}

剩餘引數

function sum(a:number,b:number,c:number,d:number):number{
		return a+b+c+d;
}
sum(1,2,3,4);
//三點運算子接受形參
function sum(...result:number[]):number{
		var sum = 0;
    for(var i = 0;i<result.length;i++){
        sum+=result[i];
    }
    return sum;
}
sum(1,2,3,4);

函式過載

首先如果是es5出現同名的方法,下面的會替代上面的方法

function css (config){

}
function css (config,value){

}

//ts中的過載

function getInfo(name:string):string;

function getInfo(age:string):number;
function getInfo(str:any):any{
	if(typeof str ==='string'){
		return '我叫'+str
    }else {
        return '我的年齡'+str;
    }
}

箭頭函式

setTimeout(()=>{
    console.log("我要做一些事情了")
},1000)
//箭頭函式this指向上下文
es5建立物件和繼承

1.es5裡面的類

最簡單的類

function Person(){
    this.name="1";
    this.age=1;
}
var p = new Person();
alert(p.name);

2.建構函式和原型鏈裡面增加的方法

function Person(){
    this.name="1";
    this.age=1;
    this.run = function(){
        console.log(this.name+"運動");
    }
}
Person.prptotype.sex="男";
Person.prptotype.work=function(){
    
}
var p = new Person();
p.work();

原型鏈上面的屬性會被多個例項分享 建構函式並不會這樣

3類裡面的靜態方法

function Person(){
    this.name="1";
    this.age=1;
    this.run = function(){
        console.log(this.name+"運動");
    }
}
Person.prototype.sex="男";
Person.prototype.work=function(){
    
}
var p = new Person();
p.work()
Person.run = function(){
    console.log("你好啊");
}
Person.run();

原型鏈上面的屬性會被多個例項分享 建構函式並不會這樣

4.es5的繼承

原型鏈+物件冒充的組合繼承模式

物件冒充

function Person(){
    this.name="1";
    this.age=1;
    this.run = function(){
        console.log(this.name+"運動");
    }
}
//物件冒充實現繼承
function Web(){
    Person.call(this)
}

var w = new Web();
w.run();//物件冒充可以繼承建構函式的屬性和方法

//物件冒充沒有辦法進行原型鏈的方法

使用原型鏈實現繼承

function Person(){
    this.name="1";
    this.age=1;
    this.run = function(){
        console.log(this.name+"運動");
    }
}
function web(){
    
}
web.prototype = new Person();
//使用原型鏈的方法實現繼承
var w = new web();
w.run();

缺點:例項化子類沒有辦法給父類進行傳參

原型鏈+建構函式的組合構造模式

function Person(name,age){
    this.name=name;
    this.age=age;
    this.run = function(){
        console.log(this.name+"運動");
    }
}
function web(name,age){
    Person.call(this.name,this.age)
}

物件冒充例項化子類可以給父類傳參

原型鏈+物件冒充的二種方法

web.prototype = person.prototype

ts中如何定義一個類

class Person{
    name:string; //屬性 前面省去了public
    constructor(n:string){
        //建構函式  例項化的時候觸發的方法
        this.name = n;
    }
    run():void{
        alert(this.name);
    }
}
var p = new Person('張三');
p.run();

ts中如何實現繼承

extends    super
class Person {
    name:string;

    constructor(name:string){
        this.name = name;
    }
    run():string{
        return `${this.name}在運動`;
    }
}

var p = new Person('王五');

p.run();

class Web extends Person{
    constructor(name:string){
        super(name);
    }
}
var w =new Web("lisi");

類裡面有三種修飾符

public  表示公有 類 子類 類外部都是可以訪問 預設為public型別
protected 保護型別  在類裡面,子類裡面可以訪問,在類外部是不能訪問的
private 私有化 類裡面可以訪問,其他都不能夠訪問

靜態方法

function Person(){
    this.run1 = function(){
        
    }
}
Person.name="哈哈哈"
Person.run()=function(){
    
}
var p = new Person();
class Person{
    private name:string;
    constructor(name:string){
        this.name=name;
    }
    run(){
        alert(`${this.name}在運動`);
    }
    work(){
        alert(`${this.name}在工作`)
    }
    //靜態方法
    static print(){
        alert('print')
    }
}
Person.print();

靜態方法沒有辦法直接呼叫 屬性

抽象類

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(){
        console.log(this.name+"吃糧食");
    }
}

var d = new Dog('asas');

d.eat();

多型

父類定義一個方法不去實現,讓繼承它的子類去實現,每個子類有不同的表現

多型屬於繼承

class Animal{
    name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(){
        console.log("吃的方法")
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name)
    }
    eat(){
        return this.name+"吃肉"
    }
}
class cat extends Animal{
    constructor(name:string){
        super(name)
    }
    eat(){
        return this.name+"吃老鼠";
    }
}
介面的概念以及屬性型別介面

介面的作用,在面向物件的程式設計中,介面是一種規範的定義,他定義了行為和動作的規範,在程式設計裡面,介面起限制個規範的作用。介面定義了某一批類所需要遵循的規範,介面沒有必要關係這些類的內部狀態和資料,也不關心類裡面方法實現的細節。他只是規定了這批類裡面需要提供某些方法,提供這些方法的類可以滿足實際需要。類似於java,但是也是在裡面增加了一些其他的東西屬性、函式、索引型別

// ts定義方法傳引數
// function printLabel(label:string):void{
//     console.log("print");
// }

//ts自定義方法對json進行約束
function printLabel(labelInfo:{label:string}):void{
    console.log("print");
}
printLabel({label:"張三"});
//對批量方法傳入引數進行約束
//介面:行為和動作規範:對批量方法進行約束

interface fullName{
    firstName:string;  //注意;結束
    secondName:string;
}
function printName(name:fullName):void{
    //必須傳入物件 firstName secondName
    console.log(name.firstName);
}
var obj = {
    firstName:'張三',
    secondName:'sa',
}
printName(obj);

輸出結果:張三
interface fullName{
    firstName:String;
    secondName:string;
    age:number;
}

function printInfo(name:fullName){
    console.log(name.firstName+name.secondName)
}
function printAge(info:fullName){
    console.log(info.age);
}
var obj ={
    age:20,
    firstName:"ma",
    secondName:"haitao",
}
printAge(obj);

輸出結果:20

介面可選屬性

ajax封裝
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("成功")
            if(config.dataType=='json'){
                JSON.parse(xhr.responseText);
            }else{
                console.log(xhr.responseText);
            }
            
        }
    }
}

ajax({
    type:'get',
    data:"name:",
    url:'www.baidu.com',
    dataType:'json',
})
函式型別介面

對於方法傳入的引數 以及返回值進行約束

1.加密函式型別介面


//加密的函式型別介面

interface encrypt{
    (key:string,value:string):string;
}

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

md5('name','zahngsan')

2.可索引介面:陣列約束

2.1陣列物件的約束

// ts定義陣列的方式
var arr:number[]=[12,12];

var arr1:Array<string>=['111','222'];
//ts中介面定義陣列的方式
interface UserArr{
    [index:number]:string;
}

var arr2:UserArr = ['1212','1212121']

console.log(arr2[0]);

2.2可索引介面對於物件的約束

3.類型別介面 對於類的約束

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+"後")
    }
}

//介面擴充套件:介面可以繼承介面

interface Animal {
    eat():void;
}

interface Person extends Animal {
    work():void;
}
泛型概念

軟體工程中,我們不僅需要建立一致性良好的API同時也是需要考慮重用性。組建不僅能夠支援當前的資料型別,同時也是能夠支援未來的資料型別

泛型主要是用來解決 類 介面 方法的複用性,以及對不特定資料型別的支援

泛型函式

//只能返回string型別資料
function getData(value:string):string{
    
    return value;
}

//同時返回string型別和number型別
function fetData1(value:any):any{
    return value;
}
//放棄了型別檢查


// T表示泛型。具體什麼類是呼叫這個方法的時候決定的
function getData<T>(value:T):T{
    return value;
}

getData<number>(123);
getData<String>('aa');


泛型類

//泛型類:比如有一個最小堆演算法,需要同時只是返回數字和字串兩種型別
//通過類的泛型來實現

class MinClass{
    public list:number[]=[];

    add(num:number){
        this.list.push(num);
    }
    min(){
        var minNum=this.list[0];
        for(var i=0;i<this.list.length;i++){
            if(minNum>this.list[i]){
                minNum=this.list[i];
            }
        }
        return minNum;
    }
}



var m=new MinClass();
m.add(2);
m.add(333);
m.add(11111);
m.add(454545);
m.min();



//改進版

class MinClass<T>{
    public list:T[]=[];

    add(num:T):void{
        this.list.push(num);
    }
    min():T{
        var minNum=this.list[0];
        for(var i=0;i<this.list.length;i++){
            if(minNum>this.list[i]){
                minNum=this.list[i];
            }
        }
        return minNum;
    }
}



var m=new MinClass<number>();
m.add(2);
m.add(333);
m.add(11111);
m.add(454545);

泛型介面

//函式型別介面
interface ConfigFn{
    (value1:string,value2:string):string;
}


var setData:ConfigFn = function(value1:string,value2:string):string{
    return value1+value2;
}

setData('name','張三');

// 泛型型別介面
interface ConfigFn{
    <T>(value1:T):T;
}

var getData:ConfigFn = function<T>(value:T){
    return value;
}

getData<string>('asa');





interface ConfigFn{
    <T>(value1:T):T;
}

function getData<T>(value:T):T{
    return value;
}

var myGetData:ConfigFn<string>=getData;

myGetData('23')
// 泛型類深入講解
// 1.定義一個類
// 2.把類作為引數約束資料傳入的型別

class User{
    username:string | undefined;
    password:string | undefined;
}

class MysqlDb{
    add(user:User):boolean{
        return true;
    }
}

var u =new User();
u.username = '張三';
u.password = '123456';

var Db = new MysqlDb();
Db.add(u);
class ArtucleCate{
    title:string |undefined;
    desc:string |undefined
    status:number |undefined;
}

class MysqlDb{
    add(info:ArtucleCate):boolean{
        console.log(info);
        return true;
    }
}
var a =new ArtucleCate();
a.title = "國內";
a.desc = "國內新聞";
a.status = 1;

var Db = new MysqlDb();
Db.add(a); 

利用泛型進行實現

class MysqlDb<T>{
    add(info:T):boolean{
        console.log(info);
        return true;
    }
}

//想給user表增加資料
// 1、定義一個;User類和資料庫進行對映

class User{
    username:string | undefined;
    password:string | undefined;
}

var u = new User();
u.username = "張三";
u.password = "123456";

var Db =new MysqlDb();

//2定義一個ArticleCate 和資料庫進行對映
class ArticleCate {
    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    constructor(params:{
        title:string | undefined;
        desc:string | undefined;
        status?:number | undefined;
    }){
        this.title = params.title;
        this.desc = params.desc;
        this.status = params.status;
    }
}

class MysqlDb<T>{
    add(info:T):boolean{
        console.log(info);
        return true;
    }
}

var a = new ArticleCate({
    title:"分類",
    desc:"1111"
});


var Db =new MysqlDb<ArticleCate>();
Db.add(a)
TypeScript 型別、介面、類 、泛型 綜合使用--TypeScript封裝統一操作Mysql Mongodb Mssql的底層類庫
/**
 * 
 * 功能:定義一個操作資料庫的庫 支援 Mysql Mssql MongoDb
 * 要求1: Mysql MsSql MOngoDb 功能一樣 都有add updata delete get方法
 * 
 * 注意:約束統一的規範、以及程式碼的重用
 * 
 * 解決方案:需要約束規範所以要定義介面,需要程式碼重用所以要用到泛型
 * 1.介面:在面向物件的程式設計中,介面是一種定義規範,他定義了行為和動作規範
 * 2.泛型:通俗來說就是解決 類、介面、方法的複用性
 * 
 */

interface DBI<T>{
    add(info:T,id:number):boolean;
    update(info:T,id:number):boolean;
    delete(id:number):boolean;
    get(id:number):any[];
}

//定義一個操作mysql資料庫的類

//注意實現泛型介面 這個類也是一個泛型類
class MysqlDb<T> implements DBI<T>{
    add(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }    
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }

    
}


//定義一個操作mysql資料庫的類

class MySqlDb<T> implements DBI<T>{
    add(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }    
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }

    
}


//操作使用者表 定義一個User類和資料表做對映

class User{
    username:string |undefined;
    password:string |undefined;
}

var u = new User();
u.username = "張三";
u.password = "1234";

var oMysql=new MySqlDb<User>();

oMysql.add(u);
模組以及模組化封裝

內部模組稱作是名稱空間

外部模組稱作是模組,在自身的作用域執行

引入

import {getData} from './xxx/asa'
名稱空間

避免命名衝突

namespac A{

}

如果需要直接export就行了

裝飾器

裝飾器:裝飾器是一種特殊的沈明,他能夠被加到類宣告,方法,屬性或者是引數上,可以修改類的行為

通俗的講裝飾器就是一個方法:可以注入到類、方法、屬性引數上擴充套件類、屬性、方法、引數的功能

常見的裝飾器:類裝飾器、屬性裝飾器、方法裝飾器、引數裝飾器

裝飾器的寫法:普通裝飾器(無法傳參)、裝飾器工廠(可以傳參)

裝飾器是js最大的成就之一,ES7標準特性之一

//類裝飾器:在類宣告之前就被宣告
//1.類裝飾器

//裝飾器
function LogClass(params:any){
    console.log(params);
    //params就是當前類
    params.protitype.run = function(){
    
    }
    params.protitype.age = 22;
}

//呼叫裝飾器
@LogClass
class HttpClient {
    constructor(){

    }
    getData(){

    }
}

類裝飾器 裝飾器工廠

可以傳參

function LogClass(params:string){
    return function(target:any){
        console.log(target);
        console.log(params);
        target.prptotype.apiUrl = params;
    }
}

@LogClass('hello')
class HttpClient{
    constructor(){

    }
    getData(){

    }
}
var http = new HttpClient();

1、類裝飾器 

     下面是一個過載建構函式的例子。

     類裝飾器表示式會在執行時當作函式被呼叫,類的建構函式作為其唯一的引數。

     如果類裝飾器返回一個值,它會使用提供的建構函式來替換類的宣告。
*/



        /*
        function logClass(target:any){
            console.log(target);
            return class extends target{
                apiUrl:any='我是修改後的資料';
                getData(){
                    this.apiUrl=this.apiUrl+'----';
                    console.log(this.apiUrl);
                }
            }
        }


        @logClass
        class HttpClient{
            public apiUrl:string | undefined;
            constructor(){
                this.apiUrl='我是建構函式裡面的apiUrl';
            }
            getData(){
                console.log(this.apiUrl);
            }
        }

        var http=new HttpClient();
        http.getData();

        */

屬性裝飾器

/*
   2、屬性裝飾器

        屬性裝飾器表示式會在執行時當作函式被呼叫,傳入下列2個引數:
            1、對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。
            2、成員的名字。

*/



//類裝飾器
    function logClass(params:string){
        return function(target:any){
            // console.log(target);
            // console.log(params);       
            
        }
    }

//屬性裝飾器

    function logProperty(params:any){
        return function(target:any,attr:any){
            console.log(target);
            console.log(attr);
            target[attr]=params;
        }
    }
    @logClass('xxxx')
    class HttpClient{
        @logProperty('http://itying.com')
        public url:any |undefined;
        constructor(){
        }
        getData(){
            console.log(this.url);
        }
    }
    var http=new HttpClient();
    http.getData();



/*
    3、方法裝飾器
        它會被應用到方法的 屬性描述符上,可以用來監視,修改或者替換方法定義。

        方法裝飾會在執行時傳入下列3個引數:
            1、對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。
            2、成員的名字。
            3、成員的屬性描述符。

*/   
/*
/*

    //方法裝飾器一

    function get(params:any){
        return function(target:any,methodName:any,desc:any){
            console.log(target);
            console.log(methodName);
            console.log(desc);
            target.apiUrl='xxxx';
            target.run=function(){
                console.log('run');
            }
        }
    }

    class HttpClient{  
        public url:any |undefined;
        constructor(){
        }
        @get('http://www.itying,com')
        getData(){
            console.log(this.url);
        }
    }

    var http:any=new HttpClient();
    console.log(http.apiUrl);
    http.run();
*/


//方法裝飾器二

    /*
        function get(params:any){
            return function(target:any,methodName:any,desc:any){
                console.log(target);
                console.log(methodName);
                console.log(desc.value);       
                
                //修改裝飾器的方法  把裝飾器方法裡面傳入的所有引數改為string型別

                //1、儲存當前的方法

                var oMethod=desc.value;
                desc.value=function(...args:any[]){                
                    args=args.map((value)=>{
                        return String(value);
                    })
                    oMethod.apply(this,args);
                }

            }
        }

        class HttpClient{  
            public url:any |undefined;
            constructor(){
            }
            @get('http://www.itying,com')
            getData(...args:any[]){
                console.log(args);
                console.log('我是getData裡面的方法');
            }
        }

        var http=new HttpClient();
        http.getData(123,'xxx');
    */



/*
    4、方法引數裝飾器
        引數裝飾器表示式會在執行時當作函式被呼叫,傳入下列3個引數:

            1、對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。
            2、引數的名字。
            3、引數在函式引數列表中的索引。
*/

// function logParams(params:any){

//     return function(target:any,methodName:any,paramsIndex:any){

//         console.log(params);

//         console.log(target);

//         console.log(methodName);

//         console.log(paramsIndex);


//         target.apiUrl=params;

//     }   

// }

// class HttpClient{  
//             public url:any |undefined;
//             constructor(){
//             }           
//             getData(@logParams('xxxxx') uuid:any){               
//                 console.log(uuid);
//             }
//  }


//  var http:any = new HttpClient();
//  http.getData(123456);
// console.log( http.apiUrl);










//裝飾器執行順序


//屬性》方法》方法引數》類

// 如果有多個同樣的裝飾器,它會先執行後面的


function logClass1(params:string){
    return function(target:any){
      console.log('類裝飾器1')
    }
}

function logClass2(params:string){
    return function(target:any){
      console.log('類裝飾器2')
    }
}

function logAttribute1(params?:string){
    return function(target:any,attrName:any){
      console.log('屬性裝飾器1')
    }
}

function logAttribute2(params?:string){
    return function(target:any,attrName:any){
      console.log('屬性裝飾器2')
    }
}

function logMethod1(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法裝飾器1')
    }
}
function logMethod2(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法裝飾器2')
    }
}



function logParams1(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法引數裝飾器1')
    }
}

function logParams2(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法引數裝飾器2')
    }
}



@logClass1('http://www.itying.com/api')
@logClass2('xxxx')
class HttpClient{
    @logAttribute1()
    @logAttribute2()
    public apiUrl:string | undefined;
    constructor(){
    }

    @logMethod1()
    @logMethod2()
    getData(){
        return true;
    }

    setData(@logParams1() attr1:any,@logParams2() attr2:any,){

    }
}

var http:any=new HttpClient();