这篇文章我们来看一下TS里面的函数

函数声明

  在 JavaScript 中,有两种常见的定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression):

  1. // 函数声明(Function Declaration)
  2. function sum(x, y) {
  3. return x + y;
  4. }
  5.  
  6. // 函数表达式(Function Expression)
  7. let mySum = function (x, y) {
  8. return x + y;
  9. };

一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到,其中函数声明的类型定义较简单:

  1. function sum(x:number,y:number):number{
  2. return x+y
  3. }

注意,输入多余的或者少于要求的参数,是不被允许的

  1. sum(, , );
  2.  
  3. // index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
  1. sum();
  2.  
  3. // index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.

函数表达式

  如果要我们现在写一个对函数表达式(Function Expression)的定义,可能会写成这样

  1. let mySun = function(x:number,y:number):number{
  2. return x + y
  3. }

这是可以通过编译的,不过事实上,上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的 mySum,是通过赋值操作进行类型推论而推断出来的。如果需要我们手动给 mySum 添加类型,则应该是这样:

  1. let mySum(x:number,y:number)=>number = function(x:number,y:number):number{
  2.   return x+y}

注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>

在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。

在 ES6 中,=> 叫做箭头函数,应用十分广泛,

用接口定义函数的形状

我们也可以使用接口的方式来定义一个函数需要符合的形状:

  1. interface SearchFunc{
  2. source:string,subString:string):boolean
  3. }
  4.  
  5. let mySearch:SearchFunc;
  6. mySearch = function(source: string,subString:string){
  7. return source.search(subString) !== -
  8. }

可选参数

前面提到,输入多余的(或者少于要求的)参数,是不允许的。那么如何定义可选的参数呢?

与接口中的可选属性类似,我们用 ? 表示可选的参数:

  1. function buildName(firstName: string, lastName?: string) {
  2. if (lastName) {
  3. return firstName + ' ' + lastName;
  4. } else {
  5. return firstName;
  6. }
  7. }
  8. let tomcat = buildName('Tom', 'Cat');
  9. let tom = buildName('Tom');

注意:可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必须参数了

  1. function buildName(firstName?: string, lastName: string) {
  2. if (firstName) {
  3. return firstName + ' ' + lastName;
  4. } else {
  5. return lastName;
  6. }
  7. }
  8. let tomcat = buildName('Tom', 'Cat');
  9. let tom = buildName(undefined, 'Tom');
  10.  
  11. // index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.

参数默认值

在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数:

  1. function buildName(firstName:string,lastName:string='Cat'){
  2. return firstName + ' ' + lastName;
  3. }
  4. let tomcat = buildName('Tom', 'Cat');
  5. let tom = buildName('Tom');

此时就不受「可选参数必须接在必需参数后面」的限制了:

  1. function buildName(firstName: string = 'Tom', lastName: string) {
  2. return firstName + ' ' + lastName;
  3. }
  4. let tomcat = buildName('Tom', 'Cat');
  5. let cat = buildName(undefined, 'Cat');

剩余参数

  ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数):

  1. function push(array,...items){
  2. items.forEach(function(item){
  3. array.push(item)
  4.   })
  5. }
  6.  
  7. let a = [];
  8. push(a,,,)

事实上,items 是一个数组。所以我们可以用数组的类型来定义它:

  1. function push(array:any[],...items:any[]){
  2. items.forEach(function(item){
  3. array.push(item);
  4. })
  5. }
  6.  
  7. let a = []
  8. push(a,1,2,3)

注意:rest 参数只能是最后一个参数

重载:

重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。

比如,我们需要实现一个函数 reverse,输入数字 123 的时候,输出反转的数字 321,输入字符串 'hello' 的时候,输出反转的字符串 'olleh'

利用联合类型,我们可以这么实现:

  1. function reverse(x: number | string): number | string {
  2. if (typeof x === 'number') {
  3. return Number(x.toString().split('').reverse().join(''));
  4. } else if (typeof x === 'string') {
  5. return x.split('').reverse().join('');
  6. }
  7. }

然而这样有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。

这时,我们可以使用重载定义多个 reverse 的函数类型:

  1. function reverse(x: number): number;
  2. function reverse(x: string): string;
  3. function reverse(x: number | string): number | string {
  4. if (typeof x === 'number') {
  5. return Number(x.toString().split('').reverse().join(''));
  6. } else if (typeof x === 'string') {
  7. return x.split('').reverse().join('');
  8. }
  9. }

上例中,我们重复定义了多次函数 reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。

注意:TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

原文链接:https://github.com/xcatliu/typescript-tutorial/blob/master/basics/type-of-function.md

TS学习随笔(五)->函数的更多相关文章

  1. PostgreSQL学习手册(五) 函数和操作符

    PostgreSQL学习手册(五) 函数和操作符 一.逻辑操作符:    常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符:    下面是Post ...

  2. TS学习随笔(七)->声明文件

    now我们来看一看TS怎么声明文件, 在JS里面我们经常会使用各种第三方类库,引入方式也不太相同,常见的就是在HTML中通过script标签引入,然后就可以使用全局变量$或者jQuery了 我们通常这 ...

  3. TS学习随笔(一)->安装和基本数据类型

    去年学过一段时间的TS,但由于在工作中不常用.就生疏了,最近项目要求用TS,那我就再回去搞搞TS,写一篇记录一下自己学习TS的进度以及TS知识点 首先,关于TS的定义我就不在这描述了,想看百度一下你就 ...

  4. TS学习随笔(三)->接口

    终于来到了比较重要的知识,接口,有多重要呢,反正是很重要好啵 在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型. 那什么是接口呢,在面向对象语言中,接口(Interf ...

  5. TS学习随笔(四)->数组的类型

    少侠们,今天我们继续来搞一搞TS 今天我们要来看一看TS中数组的定义是个什么鬼样子 数组的类型: 在 TypeScript 中,数组类型有多种定义方式,比较灵活.下面我们来看看有哪些定义方法 「类型 ...

  6. Python学习笔记(五)函数和代码复用

    函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Python提供了许多内建函数,比如print().同样,你也可以自己创建函数, ...

  7. android 学习随笔五(界面)

    把数据库内容显示到界面 清单文件设置为线性布局(5大布局属于ViewGroup) 在清单文件中可以增加View显示 LinearLayout ll = (LinearLayout) findViewB ...

  8. TS学习随笔(六)->断言

    now,我们来看一看TS里面的断言,听起来很上档次啊,其实看完你就发出惊叹,这就是断言啊 类型断言 类型断言(Type Assertion)可以用来手动指定一个值的类型 语法 <类型>值 ...

  9. Go语言学习笔记(五) [函数]

    日期:2014年7月29日   1.函数定义:func (p type) funcname(q int) (r,s int) {return 0,0 }     func: 保留字,用于定义一个函数 ...

随机推荐

  1. ASP.NET 4.0验证请求 System.Web.HttpRequestValidationException: A potentially dangerous Request.F

    System.Web.HttpRequestValidationException: A potentially dangerous Request.F 在使用类似eWebedtior 拷贝内容进去的 ...

  2. 【安富莱原创开源应用第3期】花式玩转网络摄像头之VNC远程桌面版本,稳定运行2年不死机

    说明: 1.前段时间开源了一个网络摄像头的TCP版本 https://www.cnblogs.com/armfly/p/9173167.html,这次再来一个远程VNC的版本.使用更方便,无需大家制作 ...

  3. Android 音视频开发(七): 音视频录制流程总结

    在前面我们学习和使用了AudioRecord.AudioTrack.Camera.MediaExtractor.MediaMuxer API.MediaCodec. 学习和使用了上述的API之后,相信 ...

  4. vue父子组件及非父子组件通信

    1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: <parent> <child :child-msg="msg" ...

  5. [Swift]LeetCode46. 全排列 | Permutations

    Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] O ...

  6. [Swift]LeetCode147. 对链表进行插入排序 | Insertion Sort List

    Sort a linked list using insertion sort. A graphical example of insertion sort. The partial sorted l ...

  7. [Swift]LeetCode244.最短单词距离 II $ Shortest Word Distance II

    This is a follow up of Shortest Word Distance. The only difference is now you are given the list of ...

  8. [Swift]LeetCode636. 函数的独占时间 | Exclusive Time of Functions

    Given the running logs of n functions that are executed in a nonpreemptive single threaded CPU, find ...

  9. oracle 合并多个sys_refcursor

    一.背景 在数据开发中,有时你需要合并两个动态游标sys_refcursor. 开发一个存储过程PROC_A,这个过程业务逻辑相当复杂,代码篇幅较长.一段时间后要开发一个PROC_B,要用PROC_A ...

  10. server.properties 文件详解

    [转载]:server.properties 文件详解 # 每一个Broker在集群中的唯标识.即使Broker的IP地址发生了变化,broker.id只要没变,则不会影响consumers的消息情况 ...