TypeScript学习

时间:2020-08-01
本文章向大家介绍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();

原文地址:https://www.cnblogs.com/willing6/p/13416826.html