美文网首页FETypeScript
TypeScript(五)函数

TypeScript(五)函数

作者: 一蓑烟雨任平生_cui | 来源:发表于2019-11-04 19:17 被阅读0次

    TypeScript 定义函数的四种方式

    第一种方式可以直接调用,后三种需要先实现定义的函数再调用。

    第一种 函数声明式:

    function sum (x: number, y: number): number {
      return x + y
    }
    // 调用时形参和实参一一对应
    sum(1, 2)
    

    第二种 函数表达式:

    let sum: (x: number, y: number) => number = (a, b) => a + b
    // 或
    let sumX = (a: number, b: number): number => a + b
    sum(2, 2)
    sumX(1, 4)
    

    第三种 接口实现:

    interface ISum {
      (x: number, y: number): number;
    }
    // 跟变量声明是等价的:let ISum: (a: number, b: number) => number
    let sum: ISum = (a,b) => a + b
    sum(4, 2)
    

    第四种 类型别名:(推荐方式)

    type ISum = (x: number, y: number) => number
    // 应用如下:
    let sum: ISum = (a, b) => a + b
    sum(3, 2)
    

    函数类型

    函数类型包含两部分:参数类型和返回值类型。

    1. 参数名不一定要相同,只要参数类型匹配,那么就认为它是有效的函数类型。
    const sum: (num1: number, num2: number) => number =
      function (x: number, y: number): number { return x + y }
    
    1. 返回值类型是函数类型的必要部分,如果函数没有返回任何值,必须指定返回值类型为 void 而不能留空。
    const sum: (num1: number, num2: number) => void =
      function (x: number, y: number): number { console.log(x + y) }
    

    类型推断

    如果在赋值语句的一边指定了类型但另一边没有类型的话,TypeScript编译器会自动识别出类型, 这叫做“按上下文归类”,是类型推论的一种。

    const getSum: (x: number, y: number) => number = (x, y) => x + y
    

    可选参数

    JavaScript里,每个参数都是可选的。没传参的时候,值就是undefined。但在TypeScript中函数参数默认都是必传的,必传的意思并不是不能传递null和undefined作为实参,而是编译器会检查是否为每个参数传入了值。简而言之,编译器会检查传入实参的个数是否和形参相同。

    function bar(name: string, age: number): string {
      return `${name} age is ${age}` 
    }
    
    bar('jack', 12) // ok
    bar('nike') // Expected 2 arguments, but got 1.
    bar('rose', 12, 'shanghai') // Expected 2 arguments, but got 3.
    

    TypeScript的可选参数需要在参数名后使用 ? 标识符 实现可选参数的功能。 比如上例希望 age 是可选的:

    function bar(name: string, age?: number): string {
      if (age) return `${name} age is ${age}` 
      return `the name is ${name}` 
    }
    
    bar('jack', 12) // ok
    bar('nike') // ok
    bar('rose', 12, 'shanghai') // Expected 1-2 arguments, but got 3.
    

    注意: 可选参数必须跟在必须参数后面。

    参数默认值

    可以通过为参数提供一个默认值,当参数是可选的且没有传值或传递的值是undefined时,则会使用参数的默认值。

    function fullName(firstName: string, lastName: string = 'Smith') {
      return `${firstName}  ${lastName}` 
    }
    
    fullName('Bob') // Bob  Smith
    fullName('Bob', undefined) // Bob  Smith
    fullName('Bob', 'Adams', 'Sr.')  // Expected 1-2 arguments, but got 3.
    fullName("Bob", "Adams")  // Bob  Adams 
    

    参数默认值与可选参数不同之处:

    1. 没有传值时默认参数是取默认值,而可选参数的值是undefined;
    2. 带默认值的参数不需要放在必选参数的后面。如果带默认值的参数出现在必选参数前面,则调用时必须明确的传入 undefined 值来取得默认值。

    剩余参数

    TypeScript的剩余参数和ES6的剩余参数一样。

    function sum(num1: number, ...rest: number[]): number {
      interface ITotal {
        (pre: number, cur: number): number;
      }
      const handle: ITotal = (pre, cur) => pre + cur
      return rest.reduce(handle, num1)
    }
    
    sum(1, 2, 3, 4, 5, 6, 7) // 28
    

    this

    this与箭头函数

    TypeScript在 noImplicitThis 模式下,不允许this上下文隐式定义。

    const person = {
      name: 'Mike',
      getName() {
        return function() {
          console.log(this.name)
        }
      }
    }
    const getName = person.getName()
    getName()
    

    上例函数中的this在 noImplicitThis 模式开启时报错(this' implicitly has type 'any' because it does not have a type annotation),未开启时指向window。

    可以将返回函数设置成箭头函数解决该问题。

    const person = {
      name: 'Mike',
      getName() {
        return () => {
          console.log(this.name)
        }
      }
    }
    const getName = person.getName()
    getName() // 'MIke'
    

    但上面的代码还是会存在一些问题。因为即使能够保证箭头函数里面的 this 与外层函数的this保持一致, 但是外层函数的this不一定就是 dog 这个对象。函数中的this依旧是any类型。

    this参数

    可以通过给函数添加隐式的 this 参数类型声明。this参数是个假的参数,它出现在参数列表的最前面。

    interface IPerson {
      name: string;
      getName(this: IPerson, firstName: string): () => void;
    }
    
    const person: IPerson = {
      name: 'Mike',
      getName: function(this: IPerson, firstName: string) {
        return () => {
          console.log( `${this.name} ${firstName}` )
        }
      }
    }
    const getNameX = person.getName('Mr.')
    getNameX()  // Mike Mr.
    

    回调参数里的this

    这一部分还没彻底搞清楚,国内几乎找不到深入讲解TypeScript的教程。后续补充。

    重载

    函数重载允许一个函数通过不同数量或类型的参数,返回不同类型的值。

    比如:实现一个函数 reverse,输入数字的时候,输出反转的数字,输入字符串的时候,输出反转的字符串。

    通过联合类型实现:

    function reverse(val: number | string): number | string {
      if (typeof val === 'number') {
        return Number(val.toString().split('').reverse().join(''))
      } else if (typeof val === 'string') {
        return val.split('').reverse().join('')
      }
    }
    

    联合类型的缺陷就是不能精确表达不同输入类型对应的输出类型。这时可以通过函数重载定义多个函数类型。

    函数重载实现:

    function reverse(num: number): number;
    function reverse(str: string): string;
    function reverse(val: any): any {
      if (typeof val === 'number') {
        return Number(val.toString().split('').reverse().join(''))
      } else if (typeof val === 'string') {
        return val.split('').reverse().join('')
      }
      return false
    }
    
    console.log(reverse(123456))  // 654321
    console.log(reverse('sina'))  // 'anis'
    

    以上前两个函数是函数重载列表,第三个是函数实体。

    注意:重载只能通过 function 声明。

    相关文章

      网友评论

        本文标题:TypeScript(五)函数

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