当前位置: 首页 > news >正文

【TS】TypeScript函数类型:提升函数的类型安全性和可读性


鑫宝Code

🌈个人主页: 鑫宝Code
🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础
💫个人格言: "如无必要,勿增实体"


文章目录

  • TypeScript函数类型:提升函数的类型安全性和可读性
    • 1. 引言
    • 2. 基本函数类型
      • 2.1 函数声明
      • 2.2 函数表达式
      • 2.3 箭头函数
    • 3. 可选参数和默认参数
      • 3.1 可选参数
      • 3.2 默认参数
    • 4. 剩余参数
    • 5. 函数重载
    • 6. 泛型函数
      • 6.1 泛型约束
    • 7. 函数类型接口
    • 8. 回调函数类型
    • 9. 构造函数类型
    • 10. 函数类型推断
    • 11. 高级类型与函数
      • 11.1 联合类型
      • 11.2 交叉类型
    • 12. 条件类型与函数
    • 13. 函数类型的最佳实践
    • 14. 常见陷阱和解决方案
      • 14.1 this的类型
      • 14.2 回调函数中的this
    • 15. 实际应用示例
    • 16. 结论

TypeScript函数类型:提升函数的类型安全性和可读性

1. 引言

在这里插入图片描述

在JavaScript中,函数是一等公民,它们可以被赋值给变量、作为参数传递,甚至作为其他函数的返回值。TypeScript作为JavaScript的超集,不仅继承了这些特性,还为函数添加了强大的类型系统支持。本文将深入探讨TypeScript中的函数类型,包括其定义、使用方法以及高级特性,帮助您更好地在TypeScript项目中使用函数,提高代码的类型安全性和可读性。

2. 基本函数类型

2.1 函数声明

在TypeScript中,我们可以为函数的参数和返回值添加类型注解:

function add(x: number, y: number): number {return x + y;
}

2.2 函数表达式

函数表达式也可以添加类型注解:

const multiply: (x: number, y: number) => number = function(x, y) {return x * y;
};

2.3 箭头函数

箭头函数同样支持类型注解:

const divide = (x: number, y: number): number => x / y;

3. 可选参数和默认参数

3.1 可选参数

使用?标记可选参数:

function greet(name: string, greeting?: string): string {return greeting ? `${greeting}, ${name}!` : `Hello, ${name}!`;
}

3.2 默认参数

默认参数可以与类型注解结合使用:

function createUser(name: string, age: number = 18): { name: string, age: number } {return { name, age };
}

4. 剩余参数

TypeScript支持剩余参数,并可以为其指定类型:

function sum(...numbers: number[]): number {return numbers.reduce((acc, curr) => acc + curr, 0);
}

5. 函数重载

TypeScript允许我们为同一个函数提供多个函数类型定义:

function reverse(x: string): string;
function reverse(x: number[]): number[];
function reverse(x: string | number[]): string | number[] {if (typeof x === 'string') {return x.split('').reverse().join('');} else {return x.slice().reverse();}
}

6. 泛型函数

在这里插入图片描述

泛型允许我们在定义函数时不指定具体的类型,而在使用时再指定:

function identity<T>(arg: T): T {return arg;
}let output = identity<string>("myString");

6.1 泛型约束

我们可以使用extends关键字来约束泛型类型:

interface Lengthwise {length: number;
}function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length);  // Now we know it has a .length propertyreturn arg;
}

7. 函数类型接口

我们可以使用接口来描述函数类型:

interface MathFunc {(x: number, y: number): number;
}let add: MathFunc = (x, y) => x + y;
let subtract: MathFunc = (x, y) => x - y;

8. 回调函数类型

在处理回调函数时,正确定义其类型非常重要:

function fetchData(callback: (data: string) => void): void {// 模拟异步操作setTimeout(() => {callback("Data fetched");}, 1000);
}

9. 构造函数类型

TypeScript允许我们定义构造函数的类型:

interface Point {x: number;y: number;
}interface PointConstructor {new (x: number, y: number): Point;
}function createPoint(ctor: PointConstructor, x: number, y: number): Point {return new ctor(x, y);
}

10. 函数类型推断

TypeScript能够根据上下文自动推断函数的类型:

let numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {console.log(num.toFixed(2));  // TypeScript knows 'num' is a number
});

11. 高级类型与函数

11.1 联合类型

函数可以接受或返回联合类型:

function formatValue(value: string | number): string {if (typeof value === "string") {return value.toUpperCase();}return value.toFixed(2);
}

11.2 交叉类型

交叉类型可以用来组合多个函数类型:

type Adder = (a: number, b: number) => number;
type Multiplier = (a: number, b: number) => number;type Calculator = Adder & Multiplier;const calc: Calculator = (a, b) => a + b;  // 或 a * b

12. 条件类型与函数

条件类型可以根据条件选择不同的函数类型:

type FunctionType<T> = T extends string ? (arg: string) => string : (arg: number) => number;function processValue<T extends string | number>(value: T): FunctionType<T> {if (typeof value === "string") {return ((arg: string) => arg.toUpperCase()) as FunctionType<T>;} else {return ((arg: number) => arg * 2) as FunctionType<T>;}
}

13. 函数类型的最佳实践

  1. 明确指定返回类型:虽然TypeScript可以推断返回类型,但明确指定可以提高代码可读性和可维护性。

  2. 使用函数类型别名:对于复杂的函数类型,使用类型别名可以提高可读性:

    type AsyncCallback<T> = (error: Error | null, result: T) => void;
    
  3. 利用泛型:当函数可以处理多种类型时,优先考虑使用泛型而不是any。

  4. 使用函数重载:当函数根据不同的参数有不同的行为时,使用函数重载可以提供更精确的类型信息。

  5. 避免过度使用可选参数:过多的可选参数可能导致函数调用变得复杂,考虑使用对象参数模式。

14. 常见陷阱和解决方案

14.1 this的类型

在TypeScript中,可以明确指定this的类型:

interface User {name: string;greet(this: User): void;
}const user: User = {name: "Alice",greet() {console.log(`Hello, I'm ${this.name}`);}
};

14.2 回调函数中的this

在回调函数中,this的类型可能会丢失。使用箭头函数或显式绑定可以解决这个问题:

class Handler {info: string;onEvent(this: Handler, e: Event) {// this的类型是Handlerthis.info = e.type;}
}

15. 实际应用示例

让我们通过一个实际的应用示例来展示TypeScript函数类型的强大功能:

// 定义一个表示HTTP方法的类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';// 定义一个表示API端点的接口
interface ApiEndpoint<T> {url: string;method: HttpMethod;params?: object;response: T;
}// 定义一个通用的API调用函数
async function apiCall<T>(endpoint: ApiEndpoint<T>): Promise<T> {const { url, method, params } = endpoint;const response = await fetch(url, {method,body: params ? JSON.stringify(params) : undefined,headers: {'Content-Type': 'application/json'}});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return await response.json() as T;
}// 定义一些具体的API端点
interface User {id: number;name: string;email: string;
}const getUserEndpoint: ApiEndpoint<User> = {url: '/api/user/1',method: 'GET',response: {} as User
};const createUserEndpoint: ApiEndpoint<User> = {url: '/api/user',method: 'POST',params: { name: 'New User', email: 'newuser@example.com' },response: {} as User
};// 使用apiCall函数
async function fetchUser() {try {const user = await apiCall(getUserEndpoint);console.log('Fetched user:', user.name);} catch (error) {console.error('Error fetching user:', error);}
}async function createUser() {try {const newUser = await apiCall(createUserEndpoint);console.log('Created user:', newUser.id);} catch (error) {console.error('Error creating user:', error);}
}fetchUser();
createUser();

这个例子展示了如何使用TypeScript的函数类型和泛型来创建一个类型安全的API调用系统:

  • 使用类型别名和接口定义API相关的类型
  • 创建一个泛型函数apiCall来处理不同类型的API请求
  • 使用函数重载和条件类型可以进一步改进这个系统,以处理更复杂的场景

16. 结论

TypeScript的函数类型系统为JavaScript的函数添加了强大的类型检查和安全性。通过本文的介绍,我们探讨了从基本的函数类型定义到高级特性如泛型、条件类型等多个方面。掌握这些概念和技巧,将帮助您更有效地使用TypeScript,编写出更加健壮、可维护的代码。

在实际开发中,合理运用函数类型可以大大减少运行时错误,提高代码质量。随着您在项目中不断实践,您会发现TypeScript的函数类型系统不仅能捕获潜在的错误,还能提供更好的代码提示和自动完成功能,从而提高开发效率。

继续探索和实践,相信您会在TypeScript的类型系统中发现更多精彩,让您的函数更加安全、清晰和高效!

End

相关文章:

【TS】TypeScript函数类型:提升函数的类型安全性和可读性

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 TypeScript函数类型&#xff1a;提升函数的类型安全性和可读性1. 引言2. 基本函…...

“八股文”在实际工作中是助力、阻力还是空谈?

前言&#xff1a;在当今快速发展的技术时代&#xff0c;程序员的角色变得日益重要。随着技术的不断进步&#xff0c;招聘流程也在不断演变以适应新的需求。在程序员的招聘过程中&#xff0c;“八股文”作为一种面试现象&#xff0c;已成为不可忽视的一部分。所谓“八股文”&…...

代码随想录算法训练营第22天-leetcode-回溯算法part01:

#回溯算法理论基础 能解决的问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合切割问题&#xff1a;一个字符串按一定规则有几种切割方式子集问题&#xff1a;一个N个数的集合里有多少符合条件的子集排列问题&#xff1a;N个数按一定规则全排列&…...

MySql 触发器、存储器练习

一&#xff1a; 触发器 1、建立两个表:goods(商品表)、orders(订单表) 查看数据库&#xff1a;mysql> show databases; 使用数据库&#xff1a;mysql> use mydb16_trigger; 创建goods表&#xff1a; mysql> create table goods(gid char(8) not null primary key, …...

【Plotly-驯化】一文教您画出Plotly中动态可视化饼图:pie技巧

【Plotly-驯化】一文教您画出Plotly中动态可视化饼图&#xff1a;pie技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内…...

Mirror学习笔记(一) 简介

文章目录 一、常规学习&#xff1a;Mirror核心功能有服务器和主机 二、时间戳批处理时间戳 三、TCP和UDP四、CCU(同时在线人数)五、SyncDirection(同步方向)六、RTT&#xff08;往返时间&#xff09;七、Connection Quality&#xff08;连接质量&#xff09;八、Lag Compensati…...

终端pip安装包后,Pycharm却导入失败?新手别慌,3招搞定!

很多小伙伴在学习Python的过程中,都会遇到这种情况:明明在终端用pip安装好了需要的包,但在Pycharm中导入时却报错。难道是安装姿势不对? 例如在cmd中已经有了pandas,但是去pycharm中导入pandas显示没有 先别急着怀疑人生,这很可能是因为pip安装包的路径和Pycharm项目使用…...

Redis 与 Scrapy:无缝集成的分布式爬虫技术

1. 分布式爬虫的概念 分布式爬虫系统通过将任务分配给多个爬虫节点&#xff0c;利用集群的计算能力来提高数据抓取的效率。这种方式不仅可以提高爬取速度&#xff0c;还可以在单个节点发生故障时&#xff0c;通过其他节点继续完成任务&#xff0c;从而提高系统的稳定性和可靠性…...

大厂linux面试题攻略四之Linux网络服务(一)

一、Linux网络服务-SSH服务 1.哪些设置能够提升SSH远程管理的安全等级? ssh的登录验证方式 ssh的登录端口和监听设置&#xff1a; 配置文件: /etc/ssh/sshd_config #Port 22 #ssh服务默认监听端口 #ListenAddress 0.0.0.0 #ssh服务…...

【Pulling fs layer】Linux使用docker-compose的时候,一直Pulling fs layer

当‌Docker在拉取镜像时卡在“‌pulling fs layer”阶段&#xff0c;可以通过重启Docker服务来解决。 具体步骤如下&#xff1a; 首先&#xff0c;尝试重启Docker服务。可以通过运行以下命令来重启Docker服务&#xff1a; systemctl restart docker 这个命令会重启Docker服务…...

最新保姆级教程使用WildCard开通Claude3升级ChatGPT4.0(2024.8)

如何使用 WildCard 服务注册 Claude3 随着 Claude3 的震撼发布&#xff0c;最强 AI 模型的桂冠已不再由 GPT-4 独揽。Claude3 推出了三个备受瞩目的模型&#xff1a;Claude 3 Haiku、Claude 3 Sonnet 以及 Claude 3 Opus&#xff0c;每个模型都展现了卓越的性能与特色。其中&a…...

layui 乱入前端

功能包含 本实例代码为部分傻瓜框架&#xff0c;插入引用layui。因为样式必须保证跟系统一致&#xff0c;所以大部分功能都是自定义的。代码仅供需要用layui框架&#xff0c;但原项目又不是layui搭建的提供解题思路。代码较为通用 自定义分页功能自定义筛选列功能行内编辑下拉、…...

中国十大顶级哲学家,全球公认的伟大思想家颜廷利:人类为何拥有臀部

人类为何拥有臀部&#xff1f;若众生皆无此部位&#xff0c;又如何能寻得一处真正属于自己的“座位”&#xff1f;在博大精深的中国传统文化中&#xff0c;汉字“座”与“坐”均蕴含“土”字元素。在易经的智慧里&#xff0c;作为五行之一的“土”&#xff0c;象征着人类社会的…...

Threejs中导入GLTF模型克隆后合并

很多场景中会需要同一个模型很多次&#xff0c;但是如果多次加载同一个模型会占用很高的带宽&#xff0c;导致加载很慢&#xff0c;因此就需要使用clone&#xff0c;也就是加载一个模型后&#xff0c;其他需要使用的地方使用clone的方式复制出多个同样的模型&#xff0c;再改变…...

今日arXiv最热大模型论文:北京大学最新综述:视觉大模型中的漏洞与攻防对抗

近年来&#xff0c;视觉语言大模型&#xff08;LVLM&#xff09;在文本转图像、视觉问答等任务中大放异彩&#xff0c;背后离不开海量数据、强大算力和复杂参数的支撑。 但是&#xff01;大模型看似庞大的身躯背后却有一颗脆弱的“心脏”&#xff0c;极易受到攻击。攻击者可以…...

为什么IDEA中使用@Autowired会被警告

我们在使用IDEA编码时&#xff0c;如果用到了Autowired注解注入bean&#xff0c;会发现IDEA会给代码标个波连线&#xff0c;鼠标移动上去&#xff0c;会发下idea提示&#xff1a;不推荐使用Filed injection&#xff0c;这是Spring的核心DI&#xff08;Dendency Injection&#…...

uniapp使用cover-view,使用@click无效

最近要做直播详情页面&#xff0c;用的是第三方直播链接&#xff0c;需要在该页面上放两个按钮&#xff0c;点击按钮需要弹出相关商品及优惠券。类似于抖音直播页面。 第三方链接使用的是web-view进行展示。由于该组件优先级太高&#xff0c;正常的前端组件无法在该页面浮现展…...

Postman 接口测试工具简易使用指南

一、Postman是什么? 我通过kimi问了这样一个问题&#xff0c;它给我的回答是这样的: 它的回答也算比较中规中矩&#xff0c;简单的说postman实际上就是一款接口测试工具&#xff0c;同时它还可以编写对应的测试脚本以及自动生成对应的API文档&#xff0c;结合我的习惯来说&am…...

Move生态:从Aptos和Sui到Starcoin的崛起

区块链技术自诞生以来&#xff0c;已经经历了多个发展阶段和技术迭代。近年来&#xff0c;随着智能合约平台的不断演进&#xff0c;以Move语言为核心的生态系统逐渐崭露头角。Move语言以其安全性、灵活性和高效性吸引了大量开发者和项目方的关注。在Move生态中&#xff0c;Apto…...

MacOS DockerDesktop配置文件daemon.json的位置

如果因为通过可视化页面修改配置错误导致客户端启动不起来&#xff0c;可以去找对应的配置文件通过 vim 修改后重启客户端 cd ~/.docker/...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...