• 接口


    //js写代码方式 你不知道user对象需要传入什么属性 除非你写注释什么的 注释只起个提示错误却不能提示语法错误 
    const getUserInfo = user => {
      return `name:${user.name};age:${user.age}`
    }
    getUserInfo({}) //
    //进化一下 函数调用约束对象传参; 缺点是把函数代码写的过长不方便阅读 这个时候就应该用接口了interface
    const getUserInfo1 = (user: { name: string, age: number, }): string => {
      return `name:${user.name};age:${user.age}`
    }
    getUserInfo1({ name: 'zs', age: 10 })
    //下面三种都有错误提示  
    // getUserInfo1({name:'zs'})
    // getUserInfo1({age:10})
    // getUserInfo1({name:'zs',age:10,gender:'male'})
    // 再进化一下 用interface约束对象 这个接口也可以重复使用 接口和函数定义参数实现分离

    普通接口

    直接赋值

     interface IWarningButton {
        class: "warning" //接口属性可以是具体的值
        text1: '修改'
      }
      const warningButton:IWarningButton={class: "warning",text1:'修改'} //但是赋值也是同样的值 不能改为其他值

    接口可以嵌套,有更深的子类型

     interface IPerson {
        name: string
        age: number
        job: {
          jobName: string
          place: string
        }
        interests: Array<{ name: string, lever: number }>
      }

    函数类型接口 func:interface

    第一种:传入一个一个的参数如add(a,b,c)

    直接定义一个函数类型接口

    // 如果只是简单的传入一个一个的属性给函数 直接就定义一个函数类型接口  这样就直接知道该传什么参数和不该传什么参数
    interface ISearchFunc {
      (source: string, substring: string): boolean //形参和实参是根据位置定义的
    }
    //按照位置对应的 a=>source b=>substring 名字可以相同 ;也可以不同 并且类型都可以省略
    const searchFunc1: ISearchFunc = (a, b) => { //这是最简写方式 推荐使用
      return a.includes(b)
    }
    //最完整写法
    const searchFunc2: ISearchFunc = (source: string, substring: string): boolean => {
      return source.includes(substring)
    }
    searchFunc1('abc','a)
     

    第二种,传入一个对象 比如getUserInfo(userObj) 这个时候就需要定义对象接口。函数接口看看自己习惯加不加。最好标准化一点:对象接口+函数接口

    对象接口+函数接口

    //首先定义一个对象接口
    interface IUser1 { //定义一个对象接口
      readonly id: number
      name: string
      age: number
    
    }
    // 然后定义一个函数接口 
    interface IUserInfoFunc {
      (user: IUser1): string //看这里 这里就使用了接口自定义类型 ts支持的
    }
    const getUserInfoFunc: IUserInfoFunc = user => {
      return `name:${user.name};id:${user.id};age:${user.age}`
    }
    getUserInfoFunc({ name: 'zs', age: 10, id: 1000 }) //传入一个对象

    只定义对象接口 

    interface IUser {
      name: string
      age: number
      gender?: string
      readonly id: number //只读属性 也是必须参数
    }
    const getUserInfo1 =  (user: IUser): string =>{
      return `name:${user.name};id:${user.id};age:${user.age}`
    
    }

    多层对象函数接口:多个对象接口+一个函数接口

    //第一个对象接口
    interface Item {
      readonly id: number
      name: string
      age?: number
    }
    // 第二个对象接口
    interface ItemList {
      data: Item[]
    }
    interface IRenderFunc {
      (result: ItemList): void
    }
    const render: IRenderFunc = result => {
      result.data.forEach(item => {
        console.log(item.id, item.name);
      })
    }
    let result: ItemList = { //最外面对象
      data: [
        { id: 1, name: 'zs', age: 10 }, //最里面对象
        { id: 2, name: 'lisi' }
    
      ]
    }
    render(result)

    字面量类型配合接口

    字面量类型用来约束取值只能是某几个预定值中的一个。取其他值就会报错

    let num=100|200|300
    let str="abc"|"aaa"
    let aa=100|'100'
    //然后引出type定义变量
    
    type EventNames = 'click' | 'scroll' | 'mousemove';

    //传入一个request对象
      type method = 'GET' | 'get' | 'POST' | 'post'
      //定义对象接口
      interface IRequestObj {
        url: string
        method: method
      }
      interface IRequestFunc {
        (requestObj: IRequestObj): void
      }
      const request: IRequestFunc = requestObj => {
        console.log(requestObj.url, requestObj.method);
      }
      //use
      request({ url: 'https://www.jianshu.com/p/78b750fb9cd7', method: 'get' })
    
    
      // 第二种形式:一个一个传入
      interface IRequestFunc1 {
        (url: string, method: method): void //method 是上面type 定义的method
      }
      const request1: IRequestFunc1 = (url, method) => {
        console.log(url, method);
    
      }
      request1('https://www.jianshu.com/p/78b750fb9cd7', 'GET')
      
      // 或者这样传 这里的 as const 不是声明变量的关键字,而是 const 类型 ,它会让 const 声明的变量变成真正的字面量类型
      const obj = { url: 'https://www.jianshu.com/', method: 'GET' } as const
      request1(obj.url, obj.method)

    总结常见的函数类型接口

     
    interface ISearchFunc {
      (source: string, substring: string): boolean //形参和实参是根据位置定义的
    }
    interface IUserInfoFunc { (user: IUser1): string
    //看这里 这里就使用了接口自定义类型 }
    interface ICreateSquareFunc { (config: ISquareConfig): { color: string, area: number }
    //{ color: string, area: number }返回值也可以定义为一个接口 }
    interface ISquareRes { color:string; area:number; } interface ICreateSquareFunc { (config: ISquareConfig): ISquareRes //返回值类型接口 }

    类接口 implements

    TypeScript也能够用接口来明确的强制一个类去符合某种契约。

     //函数类接口 implements
      interface ISpeakFunc {
        speak: (words: string) => string // 类的实例方法必须严格按照speak定义去实现 包括参数类型、数量和返回值的类型数量
      }
      interface IEatFunc {
        eat: () => void
      }
      class Person implements ISpeakFunc, IEatFunc { //一个类可以有多个接口实现
    
        speak(a: string) { return 'aa' }
        // speak(a:number){return 'aa'} Error
        // speak(a:string,b: string){return 'aa'} Error
        eat() { }
      }
      const p = new Person()
      p.speak('a')

    接口可以继承接口 extends

    例子1

     
      //下面这种变量声明不赋值的做法是不允许的 但是ts不会报错
      let square: ISquare //变量声明方式1 ts不会编译报错 但是js之后报错 因为编译为js square默认是undefined undefined是点不出color/penWidth属性的
      square.color = 'red'
      square.penWidth = 10
      square.slideLength = 20

      let square1 = <ISquare>{} //变量声明方式2 这是强制断言 不是泛型
      square1.color = 'blue'
      square1.penWidth = 100
      square1.slideLength = 200

     例子2

     interface ISpeakObj {
        speak: (words: string) => string
      }
      // 接口继承
      interface ISpeakChinese extends ISpeakObj {
        speakChinese: (words: string) => string
    
      }
      // 对象必须实现speak方法
      const obj: ISpeakChinese = {
        speak: (word): string => { return word }, //这里其实是没有必要再重新申明类型。不能改变 已经定下来了
        speakChinese: (words) => words //这是最好得方式
      }

    接口多继承

      interface IFly {
        fly: (location: string) => string //这些通通都是属性接口 和name:string性质是一样的
      }
      interface ISwim {
        swim: (location: string) => string
      }
      interface ISport extends ISwim, IFly { //接口多继承
        jump: (meter: number) => number
      }
      let sport: ISport = { //对象必须得去实现所有接口里面得所有方法
        fly: (a) => a,//这里就不用再给a定义数据类型了 就是string类型,而且还不能改a的数据类型 
        swim(b) { return b }, //也可以用普通函数 但是为了统一和习惯 都用箭头函数
        jump: meter => meter
      }

    接口继承type

     type Animal ={
       name:string
       age: number
     }
     interface Dog extends Animal{}
     let dog:Dog = {name:'小辉',age:1}
     

    接口继承类

     class Person{
        name:string
        age:number
      }
      
    
      interface IPerson extends Person{}
      const p1:IPerson={name:'zs',age:18}
  • 相关阅读:
    一种复杂的情感--“外戚”
    追~
    神受的孩子
    不好的习惯
    思杨改编的朝代歌
    siyang入厕
    小思趣事
    今天周三啦~~时光啊
    Python(6)——装饰器
    Python(5)——关于描述符的三种操作方法
  • 原文地址:https://www.cnblogs.com/xiaoliziaaa/p/14930368.html
Copyright © 2020-2023  润新知