五、函数的注解

news/2024/4/20 2:34:09/文章来源:https://blog.csdn.net/weixin_44683942/article/details/129176244

函数的注解

函数注解

函数类型包含两部分:参数类型和返回值类型。 当写出完整函数类型的时候,这两部分都是需要的:

// 函数注解是不变的,变的是函数定义的写法
// 完整版函数定义
let myAdd: (x: number, y: number) => number =function(x: number, y: number): number { return x + y; };
// 普通函数定义
let myAdd1: (x: number, y: number) => number = function(x, y){ return x + y; 
};
// 箭头函数定义
let myAdd2: (x: number, y: number) => number = (x, y) => x + y;

只要参数类型是匹配的,那么就认为它是有效的函数类型,而不在乎参数名是否正确。

let myAdd: (baseValue: number, increment: number) => number =function(x: number, y: number): number { return x + y; };

推断类型

**ts会根据值进行类型推断:**如果你在赋值语句的一边指定了类型但是另一边没有类型的话,TypeScript编译器会自动识别出类型。

// 函数声明
function add(x:number, y:number): number {return x + y;
}
// 函数表达式
var add1 = function(x:number, y:number): number{return x + y;
}
// es6函数表达式
var add1 = (x:number, y:number): number => x + y;

函数作为对象使用接口注解

  • 函数也是对象,还可以通过接口注解函数。
interface AddInterface{(x:number, y:number): number; //这里返回值前面是冒号
}var add1: AddInterface = (x, y) => x + y;
// 接口就是一个对象
var add2: {(x:number, y:number): number} = (x, y) => x + y;
// 函数注解
var add:(x:number, y:number) => number = (x, y) => x + y;
  • 本身对象,通过接口注解对象

前两个写法是等效的, 第三种写法接口中不允许

interface AddInterface{// a是一个函数a(x:number, y:number): number//a是一个对象的一个属性,属性值为一个函数,函数的返回值是number类型a: (x:number , y:number) => number// a: function(x:number, y:number):number
}var add:AddInterface = {a: function(x:number, y:number): number{return x+y;}
}
  • 引申:使用接口注解构造函数

当接口中函数前面有new,作为构造函数的注解(这里的构造函数使用class方式模拟)

interface AddInterface{new (x:number, y:number): void
}class Test{constructor(x:number, y:number){}
}
var test: AddInterface = Test;

函数可选参数,默认参数,剩余参数

TypeScript里的每个函数参数都是必须的。简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。

可选参数

在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。

可选参数必须跟在必须参数后面。 想让last name是可选的

function buildName(firstName: string, lastName?: string) {if (lastName)return firstName + " " + lastName;elsereturn firstName;
}let result1 = buildName("Bob");  // works correctly now
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");  // ah, just right

默认参数

在TypeScript里,用户没有传递这个参数或传递的值是undefined时。 它们叫做有默认初始化值的参数。

在所有必须参数后面的带默认初始化的参数都是可选的

function buildName(firstName: string, lastName = "Smith") {return firstName + " " + lastName;
}let result1 = buildName("Bob");                  // works correctly now, returns "Bob Smith"
let result2 = buildName("Bob", undefined);       // still works, also returns "Bob Smith"
let result3 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result4 = buildName("Bob", "Adams");         // ah, just right

与普通可选参数不同的是,带默认值的参数不需要放在必须参数的后面。如果带默认值的参数出现在必须参数前面,用户必须明确的传入 undefined值来获得默认值。

function buildName(firstName = "Will", lastName: string) {return firstName + " " + lastName;
}let result1 = buildName("Bob");                  // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // okay and returns "Bob Adams"
let result4 = buildName(undefined, "Adams");     // okay and returns "Will Adams"

剩余参数

必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在JavaScript里,你可以使用 arguments来访问所有传入的参数。

在TypeScript里,你可以把所有参数收集到一个变量里:

function buildName(firstName: string, ...restOfName: string[]) {return firstName + " " + restOfName.join(" ");
}let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是你在省略号( ...)后面给定的名字,你可以在函数体内使用这个数组。

这个省略号也会在带有剩余参数的函数类型定义上使用到:

function buildName(firstName: string, ...restOfName: string[]) {return firstName + " " + restOfName.join(" ");
}let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

this和箭头函数

this和箭头函数

箭头函数能保存函数创建时的 this值,而不是调用时的值。

看一个案例

let deck = {suits: ["hearts", "spades", "clubs", "diamonds"],cards: Array(52),createCardPicker: function() {return function(){let pickedCard = Math.floor(Math.random() * 52);let pickedSuit = Math.floor(pickedCard / 13);// 指出问题:"this" 隐式具有类型 "any",因为它没有类型注释。return {suit: this.suits[pickedSuit], card: pickedCard % 13};}}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();

第二个语句执行报错,执行时内部的this指向window(严格模式下指向undefined)。

可以更改配置项,来不提示错误,但是this指向仍未确定。

“noImplicitThis”: false

想要在一开始就明确this的指向,指向对象本身,方法:

  1. 对象的函数表达式内使用箭头函数嵌套
  2. 使用一个显式的this参数。

方法一:(常用)

let deck = {suits: ["hearts", "spades", "clubs", "diamonds"],cards: Array(52),createCardPicker: function() {// NOTE: the line below is now an arrow function, allowing us to capture 'this' right herereturn () => {let pickedCard = Math.floor(Math.random() * 52);let pickedSuit = Math.floor(pickedCard / 13);return {suit: this.suits[pickedSuit], card: pickedCard % 13};}}
}

方法二:

interface Card {suit: string;card: number;
}interface Deck {suits: string[];cards: number[];// 函数的返回值是一个箭头函数,箭头函数的返回类型是Card类型createCardPicker(this: Deck): () => Card;
}let deck: Deck = {suits: ["hearts", "spades", "clubs", "diamonds"],cards: Array(52),// NOTE: The function now explicitly specifies that its callee must be of type DeckcreateCardPicker: function(this:Deck) {return () =>{let pickedCard = Math.floor(Math.random() * 52);let pickedSuit = Math.floor(pickedCard / 13);return {suit: this.suits[pickedSuit], card: pickedCard % 13};}}
}

this在回调函数里作为参数

接口中的this是void类型,即不指定this为任何类型。

// this在回调函数参数里
interface UIElement {addClickListener(onclick: (this: void, e: Event) => void): void;
}
//下面是伪代码
class Handler {info: string;onClickBad(this: Handler, e: Event) {// oops, used this here. using this callback would crash at runtimethis.info = e.message;}
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad); // error!

指定接口中回调函数参数this为void类型后,传入的函数参数也需要是void类型否则报错。

修改方法:

  1. 类原型方法中,不再使用this。
  2. 类原型方法中想要使用this,且指定this为void类型,使用箭头函数
class Handler {info: string;onClickBad(this: void, e: Event) {// 不使用this}
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad);

这是可行的因为箭头函数不会捕获this,所以你总是可以把它们传给期望this: void的函数。

class Handler {info: string;onClickGood = (e: Event) => { this.info = e.message }
}

函数重载

ts中一个函数中根据传入函数参数类型,执行不同的函数体。

这里的函数返回值类型为void,而**当函数返回值类型设为void,则函数执行的返回值仍能保持原样,保持兼容。**

function reverse(target: number | string) {if(typeof target === 'number'){console.log([target.toString()]) //[ '1236789' ]console.log([...target.toString()]) //['1', '2', '3','6', '7', '8','9']return [...target.toString()].reverse().join();}if(typeof target === 'string'){return target.split('').reverse().join('')}
}
console.log(reverse('js++')); //'++sj'
console.log(reverse(1236789)); //9,8,7,6,3,2,1

函数定义(重载的签名)相当于:

function reverse(target:number):void;
function reverse(target:string):void;

这样签名实现了返回值兼容,即返回的值的类型与void不符仍能通过检查。

实现时,至少传入一个参数。


类型别名type:给一个类型起个新名字。一般用于联合类型。

type str = string | number;
type voidFunc = () => void;
var fn1: voidFunc = () => true;
console.log(fn1()); // true

当函数返回值类型设为void,则函数执行的返回值仍能保持原样,保持兼容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73087.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

建议收藏!数据可视化大屏设计必备步骤

相信对于从事大数据相关的人员来说,数据的可视化大屏是最能展现自己工作价值的一个途径。可视化大屏就是数据分析的最后成果的展示,而如果能设计出更直观、更酷炫、更具有科技感的大屏,更能获得客户的青睐。 那么客户喜欢的究竟是怎样的可视化…

嵌入式开发:在嵌入式应用程序中混合C和C++

许多嵌入式应用程序仍使用c语言编写,但越来越多的嵌入式开发人员现在使用C语言编写程序。某些应用程序甚至共享这两种语言。这有意义吗?C是嵌入式应用中最常用的编程语言。多年来,人们一直期待着向C过渡,但过渡速度相当缓慢。但是&#xff0…

Appium自动化测试 Inspector定位Webview/H5页面元素

目录操作步骤Python操作该混合App代码Appium在操作混合App或Android App的H5页面时, 常常需要定位H5页面中的元素, 传统方式是 FQ 使用Chrome://inspect来定位元素, 环境准备相当繁琐, 不仅需要想办法FQ, 而且还需要Android设备安装Google框架以及手机版Chrome浏览器以及相应的…

问题记录-网卡丢失导致Temporary failure in name resolution

没网了,ifconfig查看一下 发现是网卡丢失 使用如下命令: sudo ifconfig eth0 up sudo dhclient解决

postgresql 数据库 主从切换 测试

postgresql 数据库 主从切换 测试 文章目录postgresql 数据库 主从切换 测试前言环境:主从切换1. 查看数据库状态:2. 备库切换主库3. 旧主库切换成备库;4 查看状态后记前言 因数据库等保需要,需要对老系统的数据库进行主从切换来…

考出PMP证书到底有没有用?

我们将从三方面分享: 1. PMP 证书在国内的含金量怎么样? 2. HR 如何看待 PMP 证书? 3. 拿到 PMP 证书后,有哪些变化? 一,PMP证书的含金量 说到 PMP 证书的含金量,相信这个问题是所有学员都…

JS语法让人困惑的点 “==与===”

在JS中有很多神奇的语法,非常让人困惑,我们就先一一道来,相信你在开发中或多或少都踩过这些坑,或者让人无法理解。 今天我们就来说下【】和【】 这题对于很多没有系统学过前端开发的技术人员来说,算个重点&#xff0c…

Spring+MVC+MYbatis注解开发

Spring常见注解 注解一:Configuration 用在类上面,加上这个注解的类可以成为一个spring的xml配置文件,使用的是java代码的配置 注解二:ComponentScan 用在类上,加上注解可以指定扫描路径 注解三:创建对…

面试 | 递归乘法【细节决定成败】

不用[ * ]如何使两数相乘❓一、题目明细二、思路罗列 & 代码解析1、野蛮A * B【不符合题意】2、sizeof【可借鉴】解析3、简易递归【推荐】① 解析&#xff08;递归展开图&#xff09;② 时间复杂度分析4、移位<<运算【有挑战性&#x1f4aa;】① 思路顺理② 算法图解…

啥是原神?女友说想要全角色语音+表情包,顺手用python把高清图也整下来了

原神全角色中日语音表情包高清图人生苦短 我用python表情包部分&#xff1a;1. 素材来自&#xff1a;2. 准备模块3. 调用浏览器驱动4. 页面滚动5. 保存数据5. 效果全角色语音高清彩图部分1.准备工具2. 准备模块3. 请求链接4. 本次目标5. 分析数据来源6. 开始代码7. 执行结果8. …

Revit操作 | 门和窗的载入与放置。

想要系统性掌握BIM技能&#xff0c;不能只停留在理论知识上&#xff0c;实操也是关键一步。 拒绝纸上谈兵&#xff0c;提升操作技巧&#xff0c;从点滴开始积累。今天我们来学习Revit实操小技巧之门和窗的载入与放置。 门和窗的载入与放置 门和窗是建筑中最常用的构件。在 Re…

单通道说话人语音分离——Conv-TasNet(Convolutional Time-domain audio separation Network)

单通道说话人语音分离——Conv-TasNet模型(Convolutional Time-domain audio separation Network) 参考文献&#xff1a;《Conv-TasNet: Surpassing Ideal Time-FrequencyMagnitude Masking for Speech Separation》 1.背景 在真实的声学环境中&#xff0c;鲁棒的语音处理通常…

Unity(二)--通过简单例子了解UGUI几个常用对象操作(Text,Image,Button)

目录 文本框等UI对象的添加Canvas 画布给Canvas添加脚本,绑定要操作的对象文本框Text的使用图像Image的使用更换图片Type:显示图片相关按钮Button的使用过渡导航事件绑定文本框等UI对象的添加 Canvas 画布 当创建一个UI元素的时候,如果没有Canvas 画布,就会自动创建一个画布…

PDMS二次开发(一)——PML类型程序类型与概念

目录前言一、PML类型与概念基础知识变量函数小例子注释PML表达式条件判断语句循环skip和break窗口程序在PDMS菜单栏中添加程序窗口自动定位PML常见控件前言 PDMS二次开发需要.net 有自带的PML语言和C# .net一般通常泛指的是C#语言 模型数据借助.NET的接口可以转换成数据库中的…

MSP430F2132IRHBR功能框图TPS259824LNRGER电路保护和电源管理解决方案芯片

概述&#xff1a;MSP430F21x2 16位超低功耗微控制器 (MCU) 是MSP430系列微控制器的一部分。这些MCU采用一种架构&#xff0c;加上5种低功耗模式&#xff0c;能在便携式测量应用中延长电池的使用寿命。这些器件具有一个强大的16位 RISC CPU、16位寄存器和用于获得最大编码效率的…

OpenStack手动分布式部署Glance【Queens版】

目录 Glance简介 1、登录数据库配置&#xff08;在controller执行&#xff09; 1.1登录数据库 1.2数据库里创建glance 1.3授权对glance数据库的正确访问 1.4退出数据库 1.5创建glance用户密码为000000 1.6增加admin角色 1.7创建glance服务 1.8创建镜像服务API端点 2、安装gla…

FinClip 的 2022 与 2023

相比往年&#xff0c;今年复盘去年与展望新年的文章来的稍慢一点。不过也希望能够借这篇文章&#xff0c;和关注 FinClip 的用户朋友们一起聊聊&#xff0c;我们在去年和今年的想法与计划。 2022 在过去的一年中&#xff0c;我们的身边发生了很多事情&#xff0c;这些事情在不…

CANoe-TestModule-vTESTstudio-Python -- 爱恨情仇

前面有聊过什么才是真正的自动化平台&#xff1b;其实说起来也是每个测试人的工作之路&#xff0c;从入门的测试执行、测试用例设计、自动化脚本开发、自动化架构开发、自动化平台开发&#xff0c;实际上我们大多数测试人都在纠结第一步的测试执行和第三步的自动化脚本开发&…

数据结构—堆(完全解析)

数据结构—堆&#xff08;完全解析&#xff09; 数据结构——堆&#xff08;Heap&#xff09;大根堆、小根堆 详解数据结构——堆 堆的基本存储 【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆 【堆/排序】堆排序的两种建堆方法 【算法】排序算法之堆排序 C…

Mybatis学习记录

Mybatis学习记录一、MyBatis简介1.1、MyBatis历史1.2、MyBatis特性1.3、MyBatis下载1.4、和其他持久化层技术对比二、MyBatis框架搭建2.1、加入依赖2.2、创建MyBatis的核心配置文件2.3、创建Mapper接口2.4、 创建MyBatis的映射文件2.5、 测试环境2.6、 加入Log4j日志功能三、核…