interface接口

作者: 泡杯感冒灵 | 来源:发表于2022-04-08 16:12 被阅读0次
    先声明2个普通函数,
    // 这两个函数在没有用TS的情况下,语法其实是有问题的,假如person传进来的是undefined,那么整个语句运行时就会报错。
    const getPersonName = (person) => {
      console.log(person.name);
    }
    
    const setPersonName = (person,name) => {
      person.name = name;
    }
    
    为了避免错误,我们需要给person一个类型注解
    const getPersonName = (person:{name:string}) => {
      console.log(person.name);
    }
    
    const setPersonName = (person:{name:string},name:string) => {
      person.name = name;
    }
    
    有通用型的一些类型的集合,我们可以把他用interface表示出来
    interface Person {
      name: string;
    }
    
    const getPersonName = (person: Person) => {
      console.log(person.name);
    }
    
    const setPersonName = (person: Person,name:string) => {
      person.name = name;
    }
    
    同样,我们也可以用类型别名来表示
    
    type Person1 =  {
      name: string;
    }
    
    const getPersonName = (person: Person1) => {
      console.log(person.name);
    }
    
    const setPersonName = (person: Person1,name:string) => {
      person.name = name;
    }
    
    interface(接口)和type(类型别名)的区别
    • interface 只能代表一个函数或者对象,没法直接代表一个基础类型
    • type可以直接代表一个基础类型
    type Person1 = string;
    
    • TS中,通用的规范是如果能用接口来表示一些类型的话,就用接口,实在不行,再用类型别名。
    当我们定义一个接口时,会遇到一种情况,就是参数的有些属性是可有可无的。这个时候,我们该怎么定义interface呢?属性后边跟问号
    // 假如age是可有可无的,这个时候我们这样定义,那么传的参数类型,就必须要有age属性,否则就报错。
    interface Person {
      name: string;
      age: number;
    }
    
    const person = {
      name:'mike'
    }
    
    getPersonName(person);
    
    // 这个时候,就需要这样定义interface
    interface Person {
      name: string;
      // age加个问号,表示这个属性,可有可无
      age?: number;
    }
    
    只读属性
    interface Person {
      readonly name: string;
      age?: number;
    }
    
    // 接口里,name属性是只读的,所以当我尝试改变name值的时候,就会报错
    const setPersonName = (person: Person,name:string):void => {
      person.name = name;
    }
    
    接口里必须要有的属性,传的时候,一定要有,否则就报错,如果接口里没有定义,但是却传了,也不会报错。
    // Person接口规定,参数必须要有name属性,age属性可有可无。
    interface Person {
      name: string;
      age?: number;
    }
    
    const getPersonName = (person: Person):void => {
      console.log(person.name);
    }
    
    // sex属性接口没有定义,也不会报错。因为Person类型要求必须要有name属性。是匹配的上的。
    const person = {
      name: 'mike',
      sex:'male'
    }
    
    getPersonName(person);
    
    但是,如果把person 这个对象字面量,直接写在方法后面,就会报错
    interface Person {
      name: string;
      age?: number;
    }
    
    const person = {
      name: 'mike',
      sex:'male'
    }
    
    getPersonName({
      name: 'mike',
      sex:'male'
    });
    
    image.png
    • 为什么传person变量不报错,而直接传对象字面量的形式传递就会报错呢?主要是因为TS会对字面量的形式进行强校验,接口定义的时候,只有name属性和一个可有可无的age属性,不能再有其他属性。而字面量多了sex属性,所以报错。
    如果接口Person,除了name和age属性之外,还可能有其他属性,但是属性的名字不确定,属性的值的类型也不确定,该怎么定义呢?
    // [propName: string]: any;的意思是,Person 多出其他的属性名字是一个字符串,值的类型是任意类型。
    interface Person {
      name: string;
      age?: number;
      [propName: string]: any;
    }
    
    • 这个时候,我们再通过字面量的形式传sex属性,就不会报错了


      image.png
    接口不仅仅可以存属性和它对应的类型,还可以存方法
    // 意思是接口Person 不单单有属性,还有say方法,方法的返回值是个字符串。
    interface Person {
      name: string;
      age?: number;
      [propName: string]: any;
      say(): string;
    }
    
    • 这个时候,就需要在参数里加上这个say方法,否则就会报错


      image.png
    • 我们给参数加了方法,并且方法有返回值,再传就不会报错了
    const person = {
      name: 'mike',
      sex: 'male',
      say() {
        return 'say hello'
      }
    }
    
    getPersonName(person);
    setPersonName(person,'lee');
    
    class 类这个概念,TS,ES6,都有类这个概念,类实际上是可以应用接口的。
    // 意思是User这个类,应用Person这个接口;
    class User implements Person {}
    
    • 类应用接口的时候,必须要有接口里的这些属性和方法,否则就会报错
    class User implements Person {
      name = 'LEE';
      say() {
        return 'hello'
      }
    }
    
    接口还可以互相继承
    interface Person {
      name: string;
      age?: number;
      [propName: string]: any;
      say(): string;
    }
    
    // 接口Teacher  继承了 接口Person 
    // 意味着,如果参数被类型注解为Teacher接口后,不单要有Person 接口的属性和方法,还要有Teacher接口的属性和方法。否则会报错
    interface Teacher extends Person {
      teach(): string;
    }
    
    const setPersonName = (person: Teacher,name:string):void => {
      person.name = name;
    }
    
    const person = {
      name: 'mike',
      sex: 'male',
      say() {
        return 'say hello'
      },
      teach() {
        return 'hello'
      }
    }
    setPersonName(person, 'lee');
    
    接口除了定义这些属性和方法之外,还可以定义一个函数的类型。
    // 这里是定义一个函数的类型声明,函数类型是SayHi 
    // 函数必须要接收一个string类型的参数,返回值也是string类型。
    interface SayHi {
      (word:string):string
    }
    
    // 用一下这个接口
    const say:SayHi = (word:string) => {
      return word;
    }
    
    interface接口,在ts编译为js后会是什么样的呢?
    • 首先运行命令 tsc --init ,这个命令会把工程初始化为一个TS工程,里边会多一个tsconfig.json这样的文件。里边会有一些配置
    • 运行 tsc demo.ts命令,编译demo.ts为demo.js
    var getPersonName = function (person) {
        console.log(person.name);
    };
    var setPersonName = function (person, name) {
        person.name = name;
    };
    var person = {
        name: 'mike',
        sex: 'male',
        say: function () {
            return 'say hello';
        },
        teach: function () {
            return 'hello';
        }
    };
    getPersonName(person);
    setPersonName(person, 'lee');
    var User = /** @class */ (function () {
        function User() {
            this.name = 'LEE';
        }
        User.prototype.say = function () {
            return 'hello';
        };
        return User;
    }());
    var say = function (word) {
        return word;
    };
    
    接口实际上,就是我们开发过程中,TS帮我们做语法提示校验的工具,真正编译成JS代码的时候,TS会把 interface 包括 type 的内容,全部剔除掉。

    相关文章

      网友评论

        本文标题:interface接口

        本文链接:https://www.haomeiwen.com/subject/hvxesrtx.html