TypeScript - 函数(中)

news2024/11/25 6:38:19

 

目录

1、编写良好泛型函数的准则

1.1 向下推送类型参数

1.2 使用较少的类型参数

1.3 类型参数应出现两次

2、可选参数

3、回调中的可选参数

4、函数重载

5、重载签名和实现签名

6、写好重载


1、编写良好泛型函数的准则

编写泛型函数很有趣,并且很容易被类型参数冲昏头脑。 类型参数过多或在不需要的地方使用约束会使推理不太成功,从而使函数的调用方感到沮丧。

1.1 向下推送类型参数

以下是编写看起来相似的函数的两种方法:

function catArr<Type>(params: Type[]) {
  return params;
}

function dogArr<Type extends any[]>(params: Type){
  return params;
}

catArr(['波斯猫', '橘猫', '拿破仑'])
dogArr(['哈士奇', '金毛', '博美'])

乍一看,这些可能看起来完全相同,但catArr是编写此函数的更好方法。其推断的返回类型为type,但dogArr的推断返回类型为any,因为TypeScript必须使用约束类型解析arr[0]表达式,而不是在调用期间“等待”解析元素。

注意:如果可能,请使用类型参数本身,而不是约束它。

1.2 使用较少的类型参数

参考上面的代码,我们改写一下:

function catArr<Type>(params: Type[], func: (arg: Type) => Type): Type[] {
  return params.filter(func);
}

function dogArr<Type, Func extends (arg: Type) => Type>
  (params: Type[], func: Func): Type[] {
  return params.filter(func);
}

我们已经创建了一个类型参数Func,它与两个值不相关。这总是一个危险信号,因为这意味着想要指定类型参数的调用方必须毫无理由地手动指定一个额外的类型参数。Func什么也没做,只是让这个函数更难阅读和推理!

注意:始终使用尽可能少的类型参数

1.3 类型参数应出现两次

有时我们忘记了一个函数可能不需要是泛型的:

function cat<Name extends string>(N: Name): string {
  console.log('猫的名字是:: ' + N );
  return N;
}
cat('拿破仑')
// 猫的名字是:: 拿破仑

我们可以很容易地编写一个更简单的版本:

function cat(N: string): string {
  console.log('猫的名字是:: ' + N );
  return N;
}
cat('拿破仑')
// 猫的名字是:: 拿破仑

请记住,类型参数用于关联多个值的类型。如果一个类型参数在函数签名中只使用过一次,那么它与任何内容都没有关联。这包括推断的返回类型;例如,如果Name是cat的推断返回类型的一部分,那么它将关联参数和返回类型,因此尽管在编写的代码中只出现一次,但仍将使用两次。

注意:如果类型参数只出现在一个位置,请重新考虑是否确实需要它

2、可选参数

JavaScript 中的函数通常采用可变数量的参数。例如数字转2,8,16进制。

function N(n: number) {
  console.log(n.toString());    // 17
  console.log(n.toString(2));   // 0001
  console.log(n.toString(8));   // 21
  console.log(n.toString(16));  // 11
}
N(17)

我们可以在 TypeScript 中对此方法进行改造,将参数标记为可选?

function N(x:number, n?: number) {
  console.log(x.toString(n));  // 17
}
N(17)

还可以提供参数默认值,例如不传进制参数默认为十六进制:

function N(x:number, n = 16) {
  console.log(x.toString(n));  // 11
}
N(17)

现在在一下内容中f函数,n 是一个数字类型,因为任何undefined参数都会被替换成10,注意,当参数是可选的时候,调用方总是可以传递未定义的参数,因为这只是模拟一个“错误”的参数:

 

function N(x : number, n? : number) {
  console.log(x.toString(n));  // 11
}
N(17)            // 17
N(17, 10)        // 17
N(17, undefined) // 17

3、回调中的可选参数

了解可选参数和函数类型表达式后,在编写调用回调的函数时很容易犯以下错误:

function catArr(arr: any[], callback: (arg: any, index?: number) => void){
  let count = arr.length;
  for(let i =0 ; i< count; i++){
    callback(arr[i], i)
  }
}

catArr(['波斯猫', '橘猫', '拿破仑'], (v) =>{
  console.log(v);
})
catArr(['波斯猫', '橘猫', '拿破仑'], (v, i) =>{
  console.log(v, i);
})

如果在回调函数的可选参数,调用原型方法时,可以会发生错误。

catArr(['波斯猫', '橘猫', '拿破仑'], (v, i) =>{
  console.log(v, i.toString());  // “i”可能为“未定义”。
})

在 JavaScript 中,如果调用的函数的参数多于参数,则忽略额外的参数。 TypeScript 的行为方式相同。 具有较少参数(相同类型)的函数始终可以取代具有更多参数的函数。

注意:为回调编写函数类型时,切勿编写可选参数,除非您打算在不传递该参数的情况下调用对应的方法。

4、函数重载

一些JavaScript函数可以在各种参数计数和类型中调用。例如,您可以编写一个函数来生成日期,该日期采用时间戳(一个参数)或月/日/年规范(三个参数)。

在TypeScript中,我们可以指定一个函数,该函数可以通过编写重载签名以不同的方式调用。为此,请编写一定数量的函数签名(通常为两个或多个),然后是函数的主体:

function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d);
  } else {
    return new Date(mOrTimestamp);
  }
}
const d1 = makeDate(12345678);
const d2 = makeDate(5, 5, 5);
const d3 = makeDate(1, 3);     // 没有需要 2 参数的重载,但存在需要 1 或 3 参数的重载。

在这个例子中,我们写了两个重载:一个接受一个自变量,另一个接受三个自变量。前两个签名称为过载签名。

然后,我们编写了一个具有兼容签名的函数实现。函数有一个实现签名,但不能直接调用此签名。尽管我们在所需参数之后编写了一个带有两个可选参数的函数,但它不能用两个参数调用!

5、重载签名和实现签名

这是造成混淆的常见来源。 通常人们会写这样的代码,而不明白为什么会有错误:

 

function fn(x: string): void;
function fn() {
  // ...
}
fn();   // 应有 1 个参数,但获得 0 个。

同样,用于编写函数体的签名无法从外部“看到”。

从外部看不到实现的签名。在编写重载函数时,应该始终在函数的实现之上有两个或多个签名。

实现签名还必须与重载签名兼容。 例如,这些函数存在错误,因为实现签名与重载不匹配:

function fn(x: boolean): void;
function fn(x: string): void;  // 此重载签名与其实现签名不兼容。
function fn(x: boolean) {}

function fn(x: string): string;
function fn(x: number): boolean;   // 此重载签名与其实现签名不兼容。
function fn(x: string | number) {
  return "oops";
}

6、写好重载

与泛型一样,在使用函数重载时应遵循一些准则。 遵循这些原则将使函数更易于调用、更易于理解和更易于实现。

让我们考虑一个返回字符串或数组长度的函数:

 

function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
  return x.length;
}

这个功能很好;我们可以用字符串或数组调用它。 但是,我们不能使用可能是字符串数组的值来调用它,因为 TypeScript 只能将函数调用解析为单个重载:

len(""); // OK
len([0]); // OK
len(Math.random() > 0.5 ? "hello" : [0]);


// 没有与此调用匹配的重载。
//   第 1 个重载(共 2 个),“(s: string): number”,出现以下错误。
//     类型“number[] | "hello"”的参数不能赋给类型“string”的参数。
//       不能将类型“number[]”分配给类型“string”。
//   第 2 个重载(共 2 个),“(arr: any[]): number”,出现以下错误。
//     类型“number[] | "hello"”的参数不能赋给类型“any[]”的参数。
//       不能将类型“string”分配给类型“any[]”。

由于两个重载具有相同的参数计数和相同的返回类型,因此我们可以改为编写函数的非重载版本:

function len(x: any[] | string) {
  return x.length;
}

这要好得多! 调用方可以使用任何一种值来调用它,作为额外的好处,我们不必找出正确的实现签名。

注意:尽可能首选具有联合类型的参数,而不是重载。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kibana对索引库的操作(3)

这里我们主要是对索引库进行各种查询的操作,所以要提前准备一些数据 POST /leq/goods/3 {"title": "小米手机","images": "3.jpg","price": 4299,"stock": 200,"saleable": true,"subTitle":…

读发布!设计与部署稳定的分布式系统(第2版)笔记20_实例层之代码

1. 术语的定义 1.1. 服务 1.1.1. 指共同协作、以单元的形式对外提供功能的跨机器进程集合 1.1.2. 一个服务可以由多种可执行文件组成 1.1.3. 一个服务可能包含来自多个可执行文件的多个进程 1.1.4. 可能对外呈现单个IP地址&#xff0c;并在后台进行负载均衡 1.1.5. 可能有…

潇洒郎: bat文件与vbs文件, 执行命令行命令以及执行时无console, reg文件注册表

截图.bat start snippingtool 锁屏.bat rundll32.exe user32.dll,LockWorkStation redis.bat cd %~dp0 redis-server.exe redis.windows.conf vbs Set ws CreateObject("Wscript.Shell") ws.run "cmd /c C:/Python27/Scripts/ride.bat",vbhide 在上…

记录好项目D23

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个基于Springboot教务管理系统 一、系统介绍 这个项目是一个简单的教…

Slowhttptest----DoS攻击工具

Slowhttptest----DoS攻击工具 文章目录 slowhttptestcentos下安装slowhttptestUbuntu 20.04 LTS下安装slowhttptest使用 slowhttptest SlowHTTPTest 是依赖 HTTP 协议的慢速攻击 DoS 攻击工具。 工具的设计基本原理是服务器在请求完全接收后才会进行处理。 如果客户端的 HTT…

香港银行开个人账户应该选择哪个银行,附详细指南

香港现在陆续通关&#xff0c;开户是越来越方便&#xff0c;目前已经很多有账户需求的都过去开户了&#xff0c;那现在个人在香港银行开户的话可以开哪些银行呢&#xff1f;我列举了几个&#xff0c;可以参考下 汇丰个人户&#xff0c;当场开好拿卡使用 恒生个人户&#xff0…

商标注册 | 美国商标注册资料、流程、时间、方式一文详解

中国对外贸易市场中&#xff0c;美国是当仁不让的重要出口市场&#xff0c;这成为众多国内企业产品出海的先选目的地。产品出口也会涉及到一系列知识产权问题&#xff0c;而这个问题之一就是美国商标的注册。 美国的商标保护非常完善&#xff0c;它不仅可以阻止侵权商品进入美…

【ts】变量的类型注解

ts使用类型注解的好处&#xff1a;使用类型注解&#xff0c;可以使代码更加清晰和易于理解&#xff0c;在处理复杂的数据解构的时候&#xff0c;提高代码的可读性和可维护性。 在vue3中&#xff0c;类型注解是可选的&#xff0c;可用可不用&#xff0c;如果不用&#xff0c;vue…

机器学习 day22(ReLU激活函数,激活函数的种类,如何选择激活函数)

ReLU激活函数 当问题的结果是二元的&#xff0c;则a的范围是&#xff08;0&#xff0c;1&#xff09;激活函数g(z)可以用sigmoid激活函数。如果问题的结果是多元的&#xff0c;如让a的范围取(0&#xff0c;∞)&#xff0c;激活函数g(z)可以选用ReLU激活函数&#xff0c;他在z…

深入理解预训练(pre-learning)、微调(fine-tuning)、迁移学习(transfer learning)三者的联系与区别

1. 什么是预训练和微调 你需要搭建一个网络模型来完成一个特定的图像分类的任务。首先&#xff0c;你需要随机初始化参数&#xff0c;然后开始训练网络&#xff0c;不断调整参数&#xff0c;直到网络的损失越来越小。在训练的过程中&#xff0c;一开始初始化的参数会不断变化。…

prometheus进程监控配置告警及解决grafana监控面板不展示主机名问题

process_exporter进程监控及告警 监控服务器全部或某些进程是否健康&#xff0c;以及进程所占用资源是否异常使用process_exporter监测器进行进程信息的采集与node_exporter监测器相同&#xff0c;需要监测哪台服务器的进程&#xff0c;就将process_exporter监测器部署在哪台 安…

python提取GO信息

1.原始数据&#xff1a; 原始数据链接&#xff1a; http://current.geneontology.org/ontology/go-basic.obo原始数据样式&#xff1a; 2.目标格式&#xff1a; 3.代码&#xff1a; with open("go-basic.obo","r") as file:lib{}for line in file:lin…

小米面试题:Spring Boot 有哪些优点?

大家好&#xff0c;我是你们的小米&#xff01;今天我们来聊聊在Java开发领域备受瞩目的话题——Spring Boot。作为一款快速构建Java应用程序的框架&#xff0c;Spring Boot凭借其独特的优点和便利性&#xff0c;成为了众多开发者钟爱的选择。那么&#xff0c;让我们一起来看看…

MySQL数据库索引机制

文章目录 一、MySQL缓冲区二、MySQL的page1.认识单个page2.认识多个页3.聚簇索引和非聚簇索引 三、索引的操作1.创建主键索引2.创建唯一索引3.创建普通索引4.查询索引的方法5.删除索引的方法6.索引创建原则 一、MySQL缓冲区 MySQL是一款有客户端和服务端的网络应用&#xff0c…

使用CMD命令如何监听1433端口,windows下对端口的基本监听操作

使用CMD命令如何监听1433端口 开始---->运行---->cmd&#xff0c;或者是windowR组合键&#xff0c;调出命令窗口 netstat -ano |find "1433" 输入 netstat &#xff1b;设定参数 -ano &#xff1b;输入分隔符 | ;输入参数 find &#xff1b;设定要监听的…

Zabbix监控系统及安装部署

Zabbix监控系统系统及安装部署 一、Zabbix的概念二、zabbix 监控原理三、zabbix的综合对比四、Zabbix 6.0 新特性Ⅰ、Zabbix server高可用防止硬件故障或计划维护期的停机&#xff1a;Ⅱ、Zabbix 6.0 LTS新增Kubernetes监控功能&#xff0c;可以在Kubernetes系统从多个维度采集…

走进人工智能|机器人技术 人机协作新纪元

前言&#xff1a; 机器人技术为人类提供协助、增强生产力&#xff0c;改善生活质量&#xff0c;并推动科技进步和社会发展。 文章目录 序言背景核心技术支持人机协作新纪元目前形式领跑人困难和挑战 总结 机器人技术作为现代科技领域的重要研究方向&#xff0c;已经在各个领域展…

电脑Tab键有什么功能?6个实用功能总结!

我最近对电脑的键盘很有兴趣&#xff0c;想了解一下各个键有什么特殊的用法。今天正好看到Tab键&#xff0c;想问下大家知道电脑的Tab键有什么比较好用的功能吗&#xff1f; 在电脑键盘上&#xff0c;Tab键是一个常见的键&#xff0c;它具有多种功能和用途。无论是在文本处理、…

BOSHIDA DC电源模块如何选择定制代加工

BOSHIDA DC电源模块如何选择定制代加工 选择定制代加工DC电源模块需要考虑以下几个方面&#xff1a; 1. 电源模块的性能和规格&#xff1a;需要根据实际应用场景&#xff0c;确定所需的输出电压、输出电流等参数&#xff0c;并选择合适的电源模块类型&#xff0c;如开关电源模…

神经网络的量化

tinyML 的主要挑战是如何采用相对较大的神经网络&#xff08;有时约为数百兆字节&#xff09;&#xff0c;并使其适合并在资源受限的微控制器上运行&#xff0c;同时保持最小的功耗预算。 为此&#xff0c;最有效的技术称为量化&#xff08;quantization&#xff09;。 推荐&am…