typescript笔记

一、安装

npm install -g typescript

tsc -v 检测是否已安装

tsc --init 项目中创建生成tsconfig.json

“outDir”: “./js”, tsconfig.json里配置之后,ts编译的js就会放到./js文件夹里面
终端–>运行任务- ->typescript–>tsc:监听 -》这样配置就可以编辑ts自动编译成js

二、数据类型

  • boolean 、number、string
    定义变量必须定义数据类型:let a:number=12

  • array 数组定义方法:
    let arr:number[]=[1,2,3] 数组元素只能是数字类型,其他类型以此类推
    let arr:Array<number>=[1,2,3]

  • tuole(元组类型、数组中的一种)
    let arr:[string,number,boolean]=["12",12.2,true]

  • enum 枚举类型
    enum Flag{success=1,error=-1}
    let f:Flag=Flag.success
    如果没有赋值,则为其索引,f为0
    enum Flag{success,error}
    let f:Flag=Flag.success
    如果部分赋值部分不赋值,不赋值的值则以上一个值的值+1
    enum Flag{success,error=5,red}
    let f:Flag=Flag.success 0
    let f:Flag=Flag.error 5
    let f:Flag=Flag.red 6

  • any 任意类型
    let num:any=12
    let oBox:any=document.getElementById('box')
    oBox.style.color='red'

  • null 、undefined 其他(never类型)类型的子类型
    let val:undefined=12
    let val:number | undefined
    let val:number | undefined | null

  • void 表示没有任何类型,一般用于定义方法的时候方法没有返回值
    function run():void{ console.log(111111111) }

  • never 其他类型 包含null和undefined,代表从不会出现的值,意味着声明never的变量只能被never类型所赋值
    let a:never;
    a=(()=>{ throw new Error('错误')})()

三、函数

1、声明函数

  • 函数声明法
    function run():number{ return 111111111 }
  • 匿名函数法
    let run=function():number{ return 111111111 }

2、函数传参

  • 普通传参
let run=function(num:number,text:string):string{
    return `${num}--${text}`
}`
  • 可选参数
    es5中实参和形参可以不一样,但是ts中必须一样,如果不一样需要配置可选参数
let run=function(num:number,text?:string):string{
    return `${num}--${text}`
}`
run(1) //可选参数不传极了一个问号,这样写就不会报错
  • 默认参数
    es5不能设置默认参数,es6和ts可以设置默认参数
let run=function(num:number,text:string='好'):string{
    return `${num}--${text}`
}
run(1) 
  • 剩余参数
let run=function(...result:number[]):string{
	let sum =0
	for(let i=0;i<result.length;i++){
		sum+=result[i]
	}
    return sum 
}
let run=function(a:number,...result:number[]):string{
	let sum =a
	for(let i=0;i<result.length;i++){
		sum+=result[i]
	}
    return sum 
}

3、函数的重载

Java中方法的重载:指的是两个或两个以上同名函数,但参数不一样,这时会出现函数的重载
typescript中的重载:通过为同一个函数类型定义来实现多种功能的目的

 function getInfo(name:string):string;
 function getInfo(age:number):number;
 function getInfo(str:any):any{
 	if(typeof str ==='string'){
 		return '我是'+str
 	}else{
 		return '年龄'+str
 	}
 };
 

四、类

1、定义

》》》》es5

  • 对象冒充实现继承
Person(){
	this.name:"张三"
}
Person.prototype.sex="男"
function Web (){
	Person.call(this)//对象冒充实现继承,可以继承构造函数里面属性方法,没发继承原型链上面属性方法
}
let p =new Web()
console.log(p.name)//张三
console.log(p.sex)//会报错
  • 原型链实现继承
    既可以继承构造函数里面属性方法,也可以继承原型链上面属性方法
function Person(){
	this.name:"张三"
}
Person.prototype.sex="男"
function Web (){
}
Web.prototype=new Person()
let p =new Web()
console.log(p.name)//张三
console.log(p.sex)//男
  • 原型链+对象冒充的组合继承模式
function Person(name){
	this.name:name
}
Person.prototype.sex="男"
function Web (name){
Person.call(this,name)
}
Web.prototype=new Person()//第一种写法
Web.prototype= Person.prototype//第二种写法
let p =new Web("张三")
console.log(p.name)//张三
console.log(p.sex)//男

》》》》typescript

class Person{
	name:string;   //属性 前面省略了public关键词
	constructor(n:string){   //构造函数   实例化类的时候触发的方法
		this.name=n
	}
	run():void{
		console.log(this.name)
	}
}
let p =new Person("张三")
p.run()

2、继承 extends 、super

执行子类方法时,会首先匹配子类里的,如果子类没有,再去找父类里的

class Person{
	name:string;   //属性 前面省略了public关键词
	constructor(n:string){   //构造函数   实例化类的时候触发的方法
		this.name=n
	}
	run():void{
		console.log(this.name)
	}
}

class Web extends Person{
		constructor(name:string){ 
		super(name)  //初始化父类的构造函数
	}
}

3、修饰符

typescript里面定义属性的时候给我们提供了三种修饰符:

public 公有。在类里面、子类、类外面都可以访问
protected 保护类型。在类里面、子类里面可以访问,类外部不能访问
private 私有。在类里面可以访问,子类和类外部不可访问

如果不加修饰符,默认为公有

class Person{
	public name:string;   //属性 前面省略了public关键词
	constructor(n:string){   //构造函数   实例化类的时候触发的方法
		this.name=n
	}
	run():void{
		console.log(this.name)
	}
}

class Web extends Person{
		constructor(name:string){ 
		super(name)  //初始化父类的构造函数
	}
}

let b=new Web("wan")
b.run()

4、静态方法 static

实例方法是需要先先实例化才能调用,静态方法可直接用
静态方法里面没法直接调用类里面得方法

class Person{
	name:string;  
	static age:number;//静态属性
	constructor(n:string){   
		this.name=n
	}
	run():void{
		console.log(this.name)
	}
	static pint(){
		console.log("静态方法")
	}
	static getName(){
		console.log(this.name,this.age)
	}
}
let p=new Person("张三")
p.run()//张三
Person.pint()//静态方法
Person.getName()//Person undefined

  • 多态 (也属于继承):父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同得表现
class Animal {
    name: string;
    constructor(n: string) {
        this.name = n
    }
    eat(): void {
        console.log("吃")
    }
}

class Dog extends Animal {
    constructor(name: string) {
        super(name)
    }
    eat(): void {
        console.log("吃骨头")
    }
}
class Cat extends Animal {
    constructor(name: string) {
        super(name)
    }
    eat(): void {
        console.log("吃鱼")
    }
}

5、抽象类

抽象类:是提供其他类继承得基类,不能直接实例化。用abstract关键字定义抽象类和抽象方法,抽象类中得抽象方法不包含具体实现并且必须再派生类中实现
adstract抽象方法只能放在抽象类里面

  • 抽象类和抽象方法用来定义标准
    标准 Animal 这个类要求它的子类必须包含eat方法
abstract class Animal {
    public name: string;
    constructor(n: string) {
        this.name = n
    }
    abstract eat(): any;//抽点给方法不包含具体实现并且必须在派生类中实现
}

class Dog extends Animal {
    // 抽象类的子类必须实现抽象类里面的抽象方法
    constructor(name: string) {
        super(name)
    }
    eat(): void {
        console.log("吃骨头")
    }
}

五、接口 interface

接口的作用,在面向对象编程中,接口是一种规范的定义,它定义了行为和动作的规范,在编程设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里面方法的实现细节,它只规范这批类里面必须提供某些方法,提供这些方法的类就可以满足实际需求。typescript中的接口类似于Java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等

1、属性接口

对参数的约束

function printLabel(info:{label:string}):any{}
printLabel({label:"zhangsan"})

批量方法传入参数进行约束
interface

interface FullName {
    fistName: string;//必须;结束
    secondName: string;
    age?:number;//可选属性
}
function prinName(name: FullName) {
    console.log(name)
}
let obj = {
    age: 18,
    fistName: "张三",
    secondName: "里斯"
}
prinName(obj)//这样写可以不要求只含fistName、secondName
prinName({//这样写必须只含fistName、secondName
    fistName: "张三",
    secondName: "里斯"
})

ts封装ajax(这里只是写个实现效果,没有封装全)

interface Config {
    type: string;
    url: string;
    data?: string;
    dataTaye: 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(xhr.responseText) 
        } else {
            return "err"
        }
    }
}
ajax(
    {
        type: 'get',
        url: 'http://a.itying.com/api/productlist',
        dataTaye: "json"
    }
)

2、函数接口

对方法传入的参数和返回值进行约束

interface Config {
    (key: string, value: string): string
}
let p: Config = function (key: string, value: string) {
    return key + value
}
console.log(p("key", "value"))//keyvalue

3、可索引接口

对数组、对象的约束

interface UseArr {
    [index: number]: number
}
let arr: UseArr = [1]

interface UseObj {
    [index: string]: number
}
let obj: UseObj = { age: 1 }

4、类类型接口

对类的约束

interface Animal {
    name: string;
    eat(str: string): any;
}

class Dog implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name
    }
    eat(): void {
        console.log("吃骨头")
    }
}

5、接口扩展

接口可以继承接口

interface Animal {
    eat(): any;
}

interface Person extends Animal {
    name: string;
    work(): void;
}
class Web implements Person {
    name: string;
    constructor(name: string) {
        this.name = name
    }
    eat() { }
    work() { }
}

继承类+接口继承接口

interface Animal {
    eat(): any;
}

interface Person extends Animal {
    name: string;
    work(): void;
}

class Per {
    name: string;
    constructor(name: string) {
        this.name = name
    }
}
class Web extends Per implements Person {
    constructor(name: string) {
        super(name)
    }
    eat() { }
    work() { }
}

六、泛型 interface

泛型,软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

在像c#和Java这样的语言中,可以使用泛型来创建宠用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。

通俗理解,泛型就是解决 类、 接口、 方法的服用,以及对不特定数据类型的支持

  • 定义、函数
    T可以自己定义,表示泛型,具体什么类型是是调用这个方法的时候决定的
function getData<T>(value: T): T {
    return value
}
getData<number>(1)
getData<string>("黑哈哈")
class Last<T>{
    public list: T[] = [];
    add(value: T): void {
        this.list.push(value)
    }
    last(): T {
        return this.list[this.list.length - 1]
    }
}
let p = new Last<number>()
p.add(12)
p.add(13)
console.log(p.last())
  • 接口
interface Config {
    <T>(value: T): T
}
function getData<T>(value: T): T {
    return value
}
getData<number>(12)
  • 把类作为参数类型的泛型类
    把类作为参数约束数据传入的类型
class User {
    name: string | undefined;
    age: number | undefined;
}
class List {
    add(user: User): boolean {
        console.log(user)
        return true
    }
}
let p = new User()
p.name = "张三"
let u = new List()
u.add(p)
class User {
    name: string | undefined;
    age: number | undefined;
}
class List<T> {
    add(user: T): boolean {
        console.log(user)
        return true
    }
}
let p = new User()
let b = new List<User>()
p.name = "qw"
b.add(p)

七、命名空间 namespace

组织代码,避免命名冲突
一个文件里面可以有多个命名空间
命名空间里面的属性方法默认私有的,需要export暴露

namespace A {
  export class User {
    name: string | undefined;
    age: number | undefined;
  }
  export class List {
    add(user: User): boolean {
      console.log(user);
      return true;
    }
  }
}
let p = new A.List();

八、装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,可以修改类的行为。
常见的装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)

1、类装饰器

  • 普通装饰器
function logClass(params: any) {
  // params 就是当前类
  console.log(params);
  params.prototype.apiUrl = "xxx"; //动态扩展的属性
}
@logClass //不能加分号;
class HttpClient {
  constructor() {}
  getData() {}
}
let http = new HttpClient();
console.log(http);

  • 装饰器工厂
function logClass(params: string) {
  return function (target: any) {
    console.log(params);
    console.log(target);
    target.prototype.apiUrl = params;
  };
}
@logClass("api")
class HttpClient {
  constructor() {}
  getData() {}
}
let http: any = new HttpClient();
console.log(http.apiUrl);

类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。

  • 类修饰器来重载类的构造函数
function logClass(params: any) {
    return class extends params{
     apiUrl:any = "params";
     getData(){
         console.log(this.apiUrl)
     }
    };
  }

  @logClass
  class HttpClient {
    public  apiUrl:string |undefined;
    constructor() {
        this.apiUrl="内部"
    }
    getData() {
        console.log(this.apiUrl)
    }
  }
  let http: any = new HttpClient();
  http.getData()//params
  

2、属性装饰器

属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、当前属性的名称。成员的名字。

function logClass(params: any) {
    return function (target: any, attr: any) {
        console.log(target)
        console.log(attr)
        target[attr] = params
    };
}

class HttpClient {
    @logClass("123")
    public apiUrl: string | undefined;
    @logClass("7777777777")
    public apiUrl1: string | undefined;
    constructor() {
    }
    getData() {
        console.log(this.apiUrl)
        console.log(this.apiUrl1)
    }
}
let http: any = new HttpClient();
http.getData()//123   7777777777

3、方法装饰器

会被应用大方法的属性描述符上,可以用来监视、修改或者替换方法定义

方法装饰器在运行时传入3个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、属性名称
3、属性描述符

function logClass(params: any) {
    return function (target: any, name: any, desc: any) {
        target.url = "xxx"//给HttpClient扩展属性
        target.add = function () {//给HttpClient扩展方法
            console.log(params)
        }
        // 修改修饰器的方法 
        let oMethod = desc.value
        desc.value = function (...arr: any[]) {
            arr = arr.map((value) => {
                return value + "--"
            })
            oMethod.apply(this, arr)//如果不写这一句  则就变成替换方法了
        }
    };
}

class HttpClient {
    public apiUrl: string | undefined;
    constructor() {
    }
    @logClass("123")

    getData(v: any) {
        console.log(v)
    }
}
let http: any = new HttpClient();
http.add()//123
console.log(http.url)//xxx
http.getData(1)//1--

4、参数装饰器

参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入3个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、方法名称
3、参数在函数参数列表中的索引

function logClass(params: any) {
    return function (target: any, name: any, index: any) {
        target[name](params)//123
        target.apiUrl = params
    };
}

class HttpClient {
    public apiUrl: string | undefined;
    constructor() {
    }
    getData(@logClass("123") v: any) {
        console.log(v + this.apiUrl)
    }
}
let http: any = new HttpClient();
http.getData(1)//1123

  • 执行顺序
function logClass(params: any) {
    return function (target: any) {
        console.log("类1")
    };
}
function logClass2(params: any) {
    return function (target: any) {
        console.log("类2")
    };
}
function logAttr(params: any) {
    return function (target: any, attr: any) {
        console.log("属性1")
    };
}
function logAttr1(params: any) {
    return function (target: any, attr: any) {
        console.log("属性2")
    };
}
function logM(params: any) {
    return function (target: any, attr: any) {
        console.log("方法1")
    };
} function logM1(params: any) {
    return function (target: any, attr: any) {
        console.log("方法2")
    };
}
function logC(params: any) {
    return function (target: any, attr: any, index: any) {
        console.log("参数1")
    };
}
function logC1(params: any) {
    return function (target: any, attr: any, index: any) {
        console.log("参数2")
    };
}
@logClass(12)
@logClass2(12)
class HttpClient {
    @logAttr(12)
    public apiUrl: string | undefined;
    @logAttr1(12)
    public apiUrl1: string | undefined;
    constructor() {
    }
    @logM(12)
    getData(@logC("123") v: any, @logC1("123") v1: any) {
        console.log(this.apiUrl)
    }
    @logM1(12)
    getData1(@logC("123") v: any, @logC1("123") v1: any) {
        console.log(this.apiUrl)
    }
}
let http: any = new HttpClient();
http.getData(1)
// 属性1  属性2  参数2 参数1  方法1 参数2 参数1  方法2 类2 类1 undefined

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

守望黑玫瑰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值