从0到1学习typeScript

一 安装

npm install -g typescript

二 TS编译成ES5/ES6

浏览器不支持ts语法,所以需要编译成es5或es6

tsc index.ts

在这里插入图片描述

三 Typescript 开发工具 Vscode 自动编译.ts文件

1.创建tsconfig.json文件 tsc --init 生成配置文件

 tsc --init

在这里插入图片描述

2.配置json文件,改为js地址

在这里插入图片描述
在这里插入图片描述

如果有报错可以参考这连接------点我啊

四 ts数据类型

  • boolean
  • number
  • string
  • array
  • tuple(元组)
  • enum((枚举)
  • any(任意)
  • null 和 undefined
  • void
  • never

ts校验目的是为了代码更加规范,以往我们设定了常量可以随意书写不同类型,但在ts中,从一开始就写好类型后不允许变更,否则报错.

在这里插入图片描述
HTML正确引入js文件后试运行
在这里插入图片描述

数据类型与函数的定义

// ts定义数组的方式
// 第一种
let arr: String[] = ['jjhh', '2222', 'false']
// 第二种
let arr2: Array<number> = [11, 22, 33, 44]
console.log(arr);
console.log(arr2);

// 元组类型(tuple),属于数组的一种
// 元组就是可以指定数组里面每个元素的类型
let arr3: [String, Number, boolean] = ['11', 22, true]
console.log(arr3);

// 枚举类型(enum)
// 随着计算机的不断普及,程序不仅只是用于数值计算,还更广泛地用于处理非数值的数据.
// 例如:性别/月份/星期几/颜色/单位名/学历/职业等,都不是数值数据.
// 在其他程序设计语言中,一般用一个数值来表达某一个状态,则程序就很容易阅读和理解
// 也就是说,实现考虑到某一变量可能取的值,尽量用自然语言中含义清除的单词来表示它
// 的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型
// enum 枚举名{
    
    
//     标识符[=整型常数],
//     标识符[=整型常数],
//     ...true
//     标识符[=整型常数],
// }

// 例:pay 0 未支付 1支付 2交易成功
enum pay {
    
    
    未支付 = 0,
    支付 = 1,
    交易成功 = 2
}

let p: pay = pay.未支付
console.log(p);//0

// 如果不赋值默认输出索引
enum Color {
    
     red, bule = 5, orange }
let c: Color = Color.red
let c1: Color = Color.bule
let c2: Color = Color.orange
console.log(c);//0
console.log(c1);//5
console.log(c2);//6


// 任意类型(any)

let a: any = 123
a = 'ikhh'
console.log(a);//ikhh


// undefined
let udf: undefined;//定义没赋值不会报错
console.log(udf);//undefined

let udf1: Number | undefined = 777
console.log(udf1);//777



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



// 定义函数的方法
// 函数声明法
function run1(): String {
    
    
    return '必须返回字符串'
}
console.log(run1());

// 匿名函数法
let run2 = function (): Number {
    
    
    return 134
}
console.log(run2());


// 定义方法传参
function run3(name: String, age: Number): boolean {
    
    
    return true
}
console.log(run3('字符串', 99));


// 方法可选参数
// es5里面方法的实参和形参可以不一样,但在ts中必须一样,如果不一样需要配置可选参数
// (多加一个?问号)
// 注意:可选参数必须配置到参数的最后面
function run4(name: String, age?: Number): boolean {
    
    
    return true
}
console.log(run4('字符串'))


// 默认参数
//es5里面没法设置默认参数,es6和ts中都可以设置默认参数
function run5(name: String, age: Number = 20): String {
    
    
    return `${
      
      name}----${
      
      age}`
}
console.log(run5('字符串'))//字符串----20


// 剩余运算符
// 三点运算法:方法一
function sum(...result: number[]): number {
    
    
    let sum = 0
    result.map(item => sum += item)
    return sum
}
console.log(sum(1, 2, 3, 4));//10

// 方法二
function sum2(a: number, b: number, ...result: number[]): number {
    
    
    let sum = 0
    result.map(item => sum += item)
    return sum
}
console.log(sum2(1, 2, 3, 4));//7


// 函数的重载
//Java中方法的重载:重载指的是两个或者两个以上同名函数,但它们的参数不一样,这是会出现函数重载的情况
//ts中的重载:通过为同一个函数提供多个函数类型定义来试下多种功能的目的
// ts为了兼容es5以及es6重载的写法和Java中有区别

function getInfo(name: String): string
function getInfo(age: Number): Number
function getInfo(str: any): any {
    
    
    if (typeof str === 'string') {
    
    
        return `我的名字是${
      
      str}`
    } else {
    
    
        return `我的年龄是${
      
      str}`
    }
}
console.log(getInfo('山竹'));



ts中的类

es5中的类和静态方法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/index.js"></script>
</head>
<script>
    // es5里面的类
    function Person() {
      
      //实例方法
        this.name = '山竹',
            this.age = 18
    }
    var p = new Person
    console.log(p.age);//18


    // 构造函数与原型链里面添加办法
    function Person1() {
      
      
        this.work = function () {
      
      
            console.log('在工作');
        }
    }
    Person1.prototype.sex = '女';
    Person1.prototype.run = function () {
      
      
        console.log('在运动');
    }
    var p1 = new Person1
    p1.work();//在工作
    p1.run();//在运动




    // 类里面的静态方法
    function Person2() {
      
       }
    Person2.read = function () {
      
      
        console.log('read');
    }
    Person2.read()//read




    // es5中的继承
    function Person3() {
      
      
        this.work = function () {
      
      
            console.log('在工作');
        }
    }
    Person3.prototype.sex = '女';
    Person3.prototype.run = function () {
      
      
        console.log('在运动');
    }

    // Web类继承Person类 原型链+对象冒充的组合继承模式
    function web() {
      
      
        Person3.call(this)//对象冒充实现继承
    }
    var w = new web()
    w.work()//在运动,对象冒充可以继承构造函数里面的属性和方法
    // w.run()//报错,没法继承原型链




    // 原型链实现继承
    // 既可以继承构造函数的方法也可以继承原型链上的属性和方法
    // 但实例化子类的时候没法给父类传参
    function Person4() {
      
      
        this.work = function () {
      
      
            console.log('在工作');
        }
    }
    Person4.prototype.sex = '女';
    Person4.prototype.run = function () {
      
      
        console.log('在运动');
    }
    // Web类继承Person类 原型链+对象冒充的组合继承模式
    function Web1() {
      
      
    }
    Web1.prototype = new Person4()
    var w1 = new Web1()
    w1.work()





</script>

<body>

</body>

</html>

ts中的类

ts中类的定义

// es5
// function Person(name){
    
    
//     this.name=name;
//     this.run=function(){
    
    
//         console.log(this.name);
//     }
// }
// var p=new Person('山竹')
// p.run()



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

let p = new Person('山竹')
p.run()

ts中定义类与类传值
在这里插入图片描述
ts中实现继承

在这里插入图片描述
类里面的修饰符


// ts里面定义属性的时候给我们提供了三种修饰符
/**
 * public :共有          在类里面/子类/类外面都可访问
 * protected :保护类型   在类里面/子类里面都可访问,类外部没法访问
 * private :私有         在类里面可以访问,子类/类外部都没法访问
 *
 * 属性不加修饰符默认为共有
 */



// 公有属性
class Person {
    
    
    public name: String;//公有属性
    constructor(name: String) {
    
    
        this.name = name
    }
    run(): String {
    
    
        return this.name
    }
}


class Web extends Person {
    
    
    constructor(name: String) {
    
    
        super(name)
    }
}

let w = new Web('山竹')
console.log(w.run());

保护属性

在这里插入图片描述
私有属性
在这里插入图片描述

ts中静态属性 静态方法 抽象类 多态

静态方法

静态方法没办法直接调用类里面的属性,除非实例化,或改为静态属性

在这里插入图片描述
多态

父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表现
多态也是继承的一种表现


class Animal {
    
    
    name: String;
    constructor(name: String) {
    
    
        this.name = name
    }
    eat() {
    
    //具体吃什么还不知道
        console.log('吃的方法');

    }
}


// 第一个子类继承
class Dog extends Animal {
    
    
    constructor(name: String) {
    
    
        super(name)
    }
    eat(): String {
    
    
        return `${
      
      this.name}吃狗粮`
    }
}

let d = new Dog('狗狗')
console.log(d.eat());

// 第二个子类继承
class Cat extends Animal {
    
    
    constructor(name: String) {
    
    
        super(name)
    }
    eat(): String {
    
    
        return `${
      
      this.name}吃猫粮`
    }
}

let c = new Cat('猫猫')
console.log(c.eat());




抽象方法

typeScript中的抽象类:它是提供其他类继承的基类,不能直接被实例化
用abstract关键字定义抽象类和抽象方法,抽象类中的方法不包含具体实现并且必须要派生类中实现
abstract方法只能放在抽象类里面
抽象类和抽象方法来定义标准 Animal这个类要求它的子类必须包含eat方法


abstract class Animal {
    
    
    name: String;
    constructor(name: String) {
    
    
        this.name = name
    }
    abstract eat(): any
}


// 第一个子类继承
class Dog extends Animal {
    
    
    constructor(name: String) {
    
    
        super(name)
    }
    eat(): String {
    
    
        return `${
      
      this.name}吃狗粮`
    }
}

let d = new Dog('狗狗')
console.log(d.eat());

接口的概念

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

1.属性接口

ts自定义方法传入参数,对JSON进行约束



// 1.ts自定义方法传入参数,对JSON进行约束
function printLabel(labelInfo: {
     
      label: string }): void {
    
    
    console.log('printLabel');

}
printLabel({
    
     label: '山竹回家了' })

// 2.对批量方法传入参数进行约束
// 接口:行为和动作的规范,对批量方法机型约束
// interface定义接口
interface FullName {
    
    
    firstName: string;//以;结束
    secondName: string;
}

function printName(name: FullName) {
    
    
    //必须传入对象firstName secondName
    console.log(name.firstName + '--' + name.secondName);

}

function printInfo(info: FullName) {
    
    
    //必须传入对象firstName secondName
    console.log(info.firstName + '--' + info.secondName);

}


let obj = {
    
    
    firstName: '山竹',
    secondName: '回家了'
}
// 传入的参数必须包含firstName和secondName
printName(obj)

printInfo({
    
    
    firstName: '大山竹',
    secondName: '又回家了'
})


// 3.接口,可选属性,加个问号

interface FullName2 {
    
    
    firstName: string;//以;结束
    secondName?: string;
}

function printName2(name: FullName2) {
    
    
    //必须传入对象firstName secondName
    console.log(name);

}
printName2({
    
    
    firstName: '对,没错,又是山竹'
})

在这里插入图片描述

ajax封装

// ajax封装
/**
 * $.ajax({
 * type:'GET',
 * url:'test.json',
 * data:{},
 * dataType:'json'})
 */

interface Config {
    
    
    type: string;
    url: string;
    data?: string;
    dataType: string
}

function ajax(config: Config) {
    
    
    let xhr = new XMLHttpRequest();
    xhr.open(config.url, config.url, true);
    xhr.send(config.data);
    xhr.onreadystatechange = function () {
    
    
        if (xhr.readyState == 4 && xhr.status == 200) {
    
    
            console.log('chengong');
            if (config.dataType == 'json') {
    
    
                JSON.parse(xhr.responseText)
            } else {
    
    
                console.log(xhr.responseText);
            }
        }
    }
}


ajax({
    
    
    type: 'get',
    data: '000',
    url: '1111',
    dataType: 'json'
})

2.函数类型接口

对参数与返回值进行约束,批量约束

// 函数类型接口:对方法传入的参数 以及返回值进行约束 批量

// 加密的函数类型接口
interface encrypt {
    
    
    (key: string, value: string): string
}

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

console.log(md5('name', '山竹'));

在这里插入图片描述

3.可索引接口:数组/对象的约束(不常用)

// 可索引接口----对数组约束
interface userArr {
    
    
    [index: number]: string
}

let arr: userArr = ['山竹', '回家了']
console.log(arr[0]);


// 可索引接口----对对象约束
interface userObj {
    
    
    [index: number]: string
}

let obj: userObj = ['大山竹', '回家了']
console.log(obj[0]);

在这里插入图片描述

4.类类型接口

对类的约束,与抽象类相似

// 类类型接口
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 + '吃狗粮');

    }
}

let d = new Dog('小黑')
console.log(d);

在这里插入图片描述

接口扩展:接口可以继承接口

// 接口可以继承接口
// 定义一个接口
interface Animal {
    
    
    eat(): void
}


// 接口继承接口
interface Person extends Animal {
    
    
    work(): void;
}


// 定义类
class Programmer {
    
    
    public name: string;
    constructor(name: string) {
    
    
        this.name = name
    }
    coding(code: string) {
    
    
        console.log(this.name + code);

    }
}

// 类继承并调用
// implements是一个类实现一个接口用的关键字.实现一个接口,必须实现接口中的所有方法。
class Web extends Programmer implements Person {
    
    
    constructor(name: string) {
    
    
        super(name)
    }

    eat() {
    
    
        console.log(this.name + '喜欢吃馒头');

    }
    work() {
    
    
        console.log(this.name + '写代码');

    }
}


let w = new Web('山竹')
w.eat()
w.work()
w.coding('在疯狂写代码')

效果

在这里插入图片描述

泛型

泛型:软件工程中,我们不仅要创造一致的定义良好的API,同时也要考虑可重用行.组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时可以提供十分灵活的功能.
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据.这样用户就可以以自己的数据类型来使用组件.
通俗理解:泛型就是解决 类 接口 方法的复用性,以及对不特定数据类型的支持.

1.泛型的定义与泛型函数

// 泛型:可以支持不特定的数据类型
// 要求:传入的参数和返回的参数一致

// T表示泛型,具体什么类型是调用这个方法的时候决定的
function getData<T>(value: T): T {
    
    
    return value
}

getData<number>(123)

getData<String>('123')

2.泛型类

// 类的泛型
class MinClas<T>{
    
    
    public list: T[] = []
    add(value: T): void {
    
    
        this.list.push(value)

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


let m = new MinClas<number>()
m.add(8)
m.add(89)
m.add(3)
console.log(m.min());

在这里插入图片描述

3.泛型接口

//泛型的第一种写法
interface ConfigFn {
    
    
    <T>(value: T): T
}

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

getData<String>('山竹')
getData<Number>(67868)


// 泛型的第二种写法
interface ConfigFn2<T> {
    
    
    (value: T): T
}


function getData2<T>(value: T): T {
    
    
    return value
}


let myGetData2: ConfigFn2<string> = getData2;

myGetData2('20')




4.把类作为参数类型的泛型类

/**
 * 定义一个User的类,这个类的作用就是映射数据库字段
 * 然后定义一个MysqlDb的类,这个类用于操作数据库
 * 然后把User类作为参数传入到MysqlDb中
 */

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

// class MysqlDb {
    
    
//     add(user: User): boolean {
    
    
//         console.log(user);
//         return true
//     }
// }



// 操作数据库的泛型类
class MysqlDb<T> {
    
    
    add(user: T): boolean {
    
    
        console.log(user);
        return true
    }
}


let u = new User()
console.log(u, 999);
u.username = '张三'
u.password = '11111'

let Db = new MysqlDb<User>()//这里约束,下面ADD就不可以随意传入
Db.add(u)


在这里插入图片描述

ts模块

1.创建module文件夹在js文件夹中

在这里插入图片描述
创建一个使用export导出的函数



// 方式1:

// export function getData(): any[] {
    
    
//     console.log(123);
//     return []
// }



// 方式2:
function getData(): any[] {
    
    
    console.log(123);
    return []
}


export {
    
    
    getData
}

使用import引入并使用

/**
 * 模块的概念(官方):
 * 关于术语的一点说明:请务必注意一点,ts1.5里术语名已经发生了变化.'内部模块'现在称作'命名空间'.
 * '外部模块'现在则简称为'模块',模块在其自身的作用域里执行,而不是在全局作用域里;
 * 这意味着定义一个模块里的变量,函数,类等等在模块外部是不可见的.除非你明确地使用export形式之一导出它们.
 * 相反,如果想使用其他模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用import形式之一.
 *
 * (自己理解):
 * 我们可以把一些公共的功能单独抽离成一个文件作为模块.
 * 模块里面的变量 函数 类等默认是私有的,如果我们要在外部访问模块里面的数据(变量,函数,类),
 * 暴露后我们通过import引入模块就可以使用模块里面暴露的数据(变量,函数,类)
 */

// import { getData } from "./js/module";
import {
    
     getData as get } from "./js/module";//简写
get()

在cmd打印结果
在这里插入图片描述

命名空间

/**
 * 命名空间:
 * 在代码量较大的情况下,为了避免各种变量命名相冲突,可将想死功能的函数,类,接口等防止在命名空间内
 * 同Java的包,.net的命名空间一样,ts的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象.
 * 命名空间内的对象通过export导出
 *
 * 命名空间和模块的区别:
 * 命名空间:内部模块,主要用于组织代码,避免命名冲突.
 * 模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间.
 */


// 使用namespace定制命名空间,使用export导出
namespace A {
    
    
    interface Animal {
    
    
        name: string;
        eat(): void
    }
    export class Dog implements Animal {
    
    
        name: string;
        constructor(theName: string) {
    
    
            this.name = theName
        }
        eat() {
    
    
            console.log(this.name, '吃山竹');

        }
    }
}

namespace B {
    
    
    interface Animal {
    
    
        name: string;
        eat(): void
    }
    export class Dog implements Animal {
    
    
        name: string;
        constructor(theName: string) {
    
    
            this.name = theName
        }
        eat() {
    
    
            console.log(this.name, '吃山竹');

        }
    }
}

let a = new A.Dog('山竹')
a.eat()



let b = new B.Dog('超级无敌大山竹')
b.eat()

装饰器

  • 执行顺序:属性>方法>类
  • 多个装饰器时从后到前

1.打开experimentalDecorators

在这里插入图片描述

1.类装饰器

/**
 * 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为.
 *
 * 通俗的讲装饰器就是一个方法,可以注入到类/方法/属性参数上来扩展类/属性/方法/参数的功能.
 *
 * 常见的装饰器有:类装饰器/属性装饰器/方法装饰器/参数装饰器
 *
 * 装饰器的写法:普通装饰器(无法传参)/装饰器工厂(可传参)
 *
 * 装饰器是过去几年中js最大的成就之一,已是es7的标准特性之一
 *
 */

// 1.类装饰器:类装饰器在类声明之前被声明(紧靠着类声明).类装饰器应用于类构造函数,可以用来监视,修改或替换类定义.
// 传入一个参数


// 装饰器:不修改原类的情况下添加功能

// 1.普通装饰器
// function logClass(params: any) {
    
    
//     console.log(params);//params就是当前类
//     params.prototype.apiUrl = '动态添加的属性';//扩展类的属性
//     params.prototype.run = function () {
    
    
//         console.log('我是一个run方法');
//     }
// }

// // 使用装饰器
// @logClass
// class HttpClient {
    
    
//     constructor() { }
//     getData() { }
// }

// let h: any = new HttpClient()
// console.log(h.apiUrl);
// h.run()



// 2.装饰器工厂

function logClass(params: string) {
    
    
    console.log(params);//山竹
    return function (target: any) {
    
    
        console.log(target);//类
        target.prototype.name = params
    }
}

@logClass('山竹')
class HttpClient {
    
    
    constructor() {
    
     }
    getData() {
    
     }
}


let h: any = new HttpClient()
console.log(h.name);


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

function logClass(target: any) {
    
    
    console.log(target);
    return class extends target {
    
    
        apiUrl: any = '我是修改后的数据'
        getData() {
    
    
            console.log(this.apiUrl);

        }
    }

}

@logClass
class HttpClient {
    
    
    public apiUrl: string | undefined;
    constructor() {
    
    
        this.apiUrl = '我是构造函数里面的apiUrl'
    }
    getData() {
    
    
        console.log(this.apiUrl);

    }
}
let http = new HttpClient()
http.getData()

2.属性装饰器

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

// 类的装饰器
function logClass(target: any) {
    
    
    console.log(target, 1);
}

// 属性的装饰器
function logProperty(params: any) {
    
    
    return function (target: any, attr: any) {
    
    
        console.log(target, 2);
        console.log(attr, 3);//属性名
        target[attr] = params
    }
}

// 属性装饰器

@logClass
class HttpClient {
    
    
    @logProperty('http://shanzhu.com')
    public apiUrl: string | undefined;
    constructor() {
    
     }
    getData() {
    
    
        console.log(this.apiUrl, 4);
    }
}
let http = new HttpClient()
http.getData()

在这里插入图片描述

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 = 'xxx'
//         target.run = () => {
    
    
//             console.log('run');

//         }
//     }
// }


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

//     }
// }

// let h: any = new HttpClient()
// console.log(h.apiUrl)
// h.run()



// 方法装饰器二
function get(params: any) {
    
    
    return function (target: any, methodName: any, desc: any) {
    
    
        console.log(target);
        console.log(methodName);
        console.log(desc);
        // 修改装饰器的方法,把装饰器方法里面传入的所有参数改为string类型
        // 1.保存当前的方法
        let 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')
    getData(...args: any[]) {
    
    
        console.log(args);
        console.log('我是getData里面的方法');

    }
}


let http = new HttpClient();
http.getData(123, 'xxx')

猜你喜欢

转载自blog.csdn.net/weixin_47886687/article/details/117195428