解释 TypeScript 中的类型系统,如何定义和使用类型?

1. 类型系统的核心作用

TypeScript类型系统本质上是JavaScript的静态类型增强方案,提供三个核心价值:

  • 开发阶段类型检查(类似编译时eslint)
  • 更清晰的API文档(类型即文档)
  • 更好的IDE自动补全支持

代码示例:

// 错误示范:未指定类型导致潜在隐患
function add(a, b) {return a + b;
}
add('hello', 123); // 运行时错误但编译期不报错// 正确类型标注
function add(a: number, b: number): number {return a + b;
}
add('hello', 123); // 编译时报错:类型不匹配
2. 类型定义方式(重点考察点)
(1) 基础类型
// 原生类型
let name: string = 'Alice';
let age: number = 28;
let isStudent: boolean = true;// 数组类型
let hobbies: string[] = ['reading', 'coding'];
let scores: number[] = [90, 85, 92];// 元组类型(固定长度的异构数组)
let user: [string, number] = ['Bob', 30];
(2) 接口(Interface)

用于描述对象结构的最常用方式

interface User {id: number;name: string;email?: string; // 可选属性address: {city: string;zipCode: string;};
}// 正确实现
const user: User = {id: 1,name: 'Charlie',address: { city: 'Shanghai', zipCode: '200000' }
};// 错误实现(缺少必要属性)
const invalidUser = { name: 'David' }; // 编译报错
(3) 类型别名(Type Alias)

适用于复杂类型抽象

type Point = {x: number;y: number;
};type Rectangle = {topLeft: Point;bottomRight: Point;
};// 更复杂的联合类型
type ResponseData<T> = {data: T;error?: string;
};
(4) 联合类型(Union Types)

处理多种可能类型

function processInput(value: string | number) {if (typeof value === 'string') {console.log(`String input: ${value}`);} else {console.log(`Number input: ${value.toFixed(2)}`);}
}processInput('hello');    // 执行字符串分支
processInput(42);       // 执行数字分支
processInput(true);      // 编译时报错:类型不在联合类型中
(5) 交叉类型(Intersection Types)

合并多个类型特征

interface Serializable {serialize(): string;
}class Person {name: string;age: number;
}// 创建同时满足两个条件的类型
type SerializablePerson = Person & Serializable;class SerializablePersonImpl extends Person implements Serializable {serialize() {return JSON.stringify({ name: this.name, age: this.age });}
}
3. 高级类型技巧
(1) 类型推断(Type Inference)
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {return obj[key];
}const user = { name: 'Alice', age: 30 };
const userName = getProperty(user, 'name'); // 推断为string类型
(2) 类型守卫(Type Guards)
function isNumber(value: any): value is number {return typeof value === 'number';
}function printValue(value: any) {if (isNumber(value)) {console.log(`Number: ${value}`); // 类型被缩小为number} else {console.log(`String: ${value}`); // 类型被缩小为string}
}
(3) 映射类型(Mapped Types)
type Readonly<T> = {readonly [P in keyof T]: T[P];
};interface User {name: string;age: number;
}type ReadonlyUser = Readonly<User>; 
// 所有属性变为只读
4. 日常开发实践建议
(1) 严格模式配置
{"compilerOptions": {"strict": true,"noImplicitAny": true,"strictNullChecks": true}
}
  • strict模式开启后:
    • 所有变量必须有显式类型声明
    • 不能将null/undefined赋值给非允许类型
    • 函数参数必须显式标注类型
(2) 合理使用any类型
// 不推荐
function handleData(data: any) {console.log(data.name); // 可能存在运行时错误
}// 推荐改进
function handleData(data: { name: string }) {console.log(data.name);
}// 必要时使用类型断言
const userInput = document.querySelector('#input') as HTMLInputElement;
(3) 类型安全的API设计
// 错误示范:返回不确定类型
function fetchUserData(id: number) {return fetch(`/api/users/${id}`).then(response => response.json());
}// 正确实现
interface UserResponse {id: number;name: string;email: string;
}async function fetchUserData(id: number): Promise<UserResponse> {const response = await fetch(`/api/users/${id}`);if (!response.ok) {throw new Error('Network error');}return response.json() as UserResponse; // 显式断言类型
}
(4) 类型别名的合理使用
// 不推荐过度嵌套
type DeepReadonly<T> = {readonly [P in keyof T]-?: DeepReadonly<T[P]>;
};// 推荐分层抽象
type Readonly<T> = {readonly [P in keyof T]: T[P];
};type DeepReadonly<T> = {readonly [P in keyof T]: DeepReadonly<T[P]>;
};
5. 常见陷阱与注意事项
(1) 类型合并冲突
interface A {x: number;
}interface B {x: string;
}// 合并会产生联合类型 {x: number} | {x: string}
type C = A & B; // 编译错误:类型不兼容
(2) 函数重载歧义
function process(value: number): number;
function process(value: string): string;function process(value: any) {if (typeof value === 'number') return value * 2;else return value.toUpperCase();
}// 更好的实现方式
function process<T>(value: T): T extends number ? number : string {return typeof value === 'number' ? value * 2 : value.toUpperCase();
}
(3) 类型推断失效场景
function createArray<T>(length: number, value: T): T[] {return Array(length).fill(value);
}const result = createArray(3, 'hello'); // 正确推断为string[]
const numericResult = createArray(3, 5); // 正确推断为number[]
6. 性能考量
  • 类型定义不会影响运行时性能(TS编译后生成纯JS)
  • 复杂类型系统会增加编译时间,建议:
    • 合理拆分大型类型定义
    • 使用条件类型代替深度递归结构
    • 避免不必要的类型运算符
7. 工具类型实战
// Partial类型:将所有属性变为可选
type PartialUser = Partial<User>;// Required类型:将所有属性变为必选
type RequiredUser = Required<User>;// Omit类型:排除指定属性
type PublicUser = Omit<User, 'email'>;// Extract类型:提取共有类型
type CommonProps = Extract<User, Admin>; // Readonly类型:只读属性集合
type ReadonlyUser = Readonly<User>;// Record类型:键值对映射
type AgeMap = Record<string, number>;
8. 代码质量检查清单
  1. 所有函数参数都有明确类型标注
  2. 接口/类型别名包含必要文档注释
  3. 避免使用any类型(除非绝对必要)
  4. 数组类型优先使用泛型而非any[]
  5. 对复杂类型使用有意义的命名
  6. 类型别名和接口保持单一职责
  7. 定期运行tslint/type-check进行静态分析

作为资深开发者,建议建立以下类型安全开发规范:

  1. 在团队中强制启用严格模式
  2. 使用接口描述核心数据模型
  3. 对第三方库类型进行类型声明文件(d.ts)封装
  4. 利用类型推导减少冗余标注
  5. 重要业务逻辑添加单元类型测试

通过系统性的类型设计,可以显著提升代码的可维护性和健壮性,降低运行时错误率。在实际项目中,建议从核心模块开始逐步引入严格类型检查,配合IDE的类型提示功能,形成良好的类型驱动开发习惯。

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

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

相关文章

Linux:多线程(三.POSIX信号量、生产消费模型、线程池)

目录 1. 生产者消费者模型 1.1 阻塞队列(BlockingQueue) 1.2 一个实际应用的例子 2. POSIX信号量 2.1 引入 2.2 回顾加深理解信号量 2.3 信号量的操作接口 3. 基于循环队列的生产消费模型 3.1 循环队列 3.2 整个项目 4. 线程池 4.1 概念 4.2 线程池实现 1. 生产者…

静态路由实验

一、实验拓扑图&#xff1a; 我们的实验目的是使得全网实现互通。 &#xff08;1)首先我们根据路由器的编号&#xff0c;配置好接口IP地址和 相应的环回地址&#xff1a; R1上的配置&#xff1a; [R1]Int e0/0/0 [R1]ip ad 12.1.1.1 24 [R1]int loopback 0 [R1]ip ad 1.1…

从零搭建微服务项目Pro(第3-1章——本地/OSS图片文件存取)

前言&#xff1a; 在小型demo项目中&#xff0c;一般将图片音频等字节流文件存放本地数据库&#xff0c;但企业级项目中&#xff0c;由于数据量容量有限&#xff0c;需要借助OSS来管理大规模文件。 OSS&#xff08;对象存储服务&#xff0c;Object Storage Service&#xff0…

Spring Boot 日志

目录 一、为什么要学习日志 二、认识日志格式 三、日志使用 打印日志 步骤 日志框架介绍 门面模式(外观模式) 门面模式的实现 门面模式的优点 四、日志级别 日志级别分类 日志级别的使用 日志配置 配置日志级别 日志持久化 配置日志文件分割 五、更简单的日志…

linux内存页块划分及位图存储机制

page_alloc.c - mm/page_alloc.c - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer 一. 什么是页块&#xff08;Pageblock&#xff09;&#xff1f; 定义&#xff1a;页块是物理内存中的一个连续区域&#xff0c;由 2^pageblock_order 个物理页&#xff08;Pag…

chebykan与代码3

目录 参考文献有 ‘’ 中文 各自讲了什么 切比雪夫多项式有两类吗&#xff1f;这里存疑 KAN变体 期刊 切比雪夫と爱因斯坦の约定 维度标签的含义 爱因斯坦求和约定 参考文献有 ‘’ 中文 [1] 神经网络&#xff1a;全面基础 [2] 通过sigmoid函数的超层叠近似 [3] 多层前…

DETR详解

1.概述 DETR&#xff0c;全称为Detection Transformer&#xff0c;是Facebook在ECCV2020上提出的基于Transformer的端到端目标检测网络最大的特点就是&#xff1a;不需要预定义的先验anchor&#xff0c;也不需要NMS的后处理策略&#xff0c;就可以实现端到端的目标检测。但是&…

南昌长空STONE 60A-M 无人机电调深度测评:轻量化设计与工业级安全的融合典范

引言 在无人机技术不断革新的今天&#xff0c;电调作为动力系统的核心组件&#xff0c;其性能直接影响飞行稳定性与操控体验。STONE 系列凭借 “轻量化设计” 理念&#xff0c;在竞争激烈的市场中独树一帜。本文将深度解析 STONE 60A-M 电调的技术亮点与实际表现&#xff0c;探…

初阶数据结构(C语言实现)——4.2队列

目录 2.队列2.1队列的概念及结构2.2队列的实现2.2.1 初始化队列2.2.2 销毁队列2.2.3 队尾入队列2.2.4 队头出队列2.2.5获取队列头部元素2.2.6 获取队列队尾元素2.2.7获取队列中有效元素个数2.2.8 检测队列是否为空&#xff0c;如果为空返回非零结果&#xff0c;如果非空返回0 3…

C++和OpenGL实现3D游戏编程【连载24】——父物体和子物体之间的坐标转换

欢迎来到zhooyu的C++和OpenGL游戏专栏,专栏连载的所有精彩内容目录详见下边链接: 🔥C++和OpenGL实现3D游戏编程【总览】 父子物体的坐标转换 1、本节要实现的内容 前面章节我们了解了父物体与子物体的结构,它不仅能够表示物体之间的层次关系,更重要的一个作用就是展示物…

怎么实现: 大语言模型微调案例

怎么实现: 大语言模型微调案例 目录 怎么实现: 大语言模型微调案例输入一个反常识的问题:首都在北京天安门之后对输出模型进行测试:首都在北京天安门微调代码:测试微调模型代码:微调输出模型结构输出模型参数大小对比Qwen 2.5_0.5:53MB输出模型:951MB 是一样的,没有进行…

知乎后台管理系统:数据库系统原理实验1——数据库基础概念

实验背景 通过练习绘制语义网络&#xff0c;加深对于基本概念之间关系的理解和掌握。掌握在VISIO中绘制能准确表达基本概念之间关系的语义网络的技能。了解并比较数据模型的Chen’s表示法和UML表示法。理解关系模型设计中的完整性约束的重要性。掌握在Linux操作系统下远程访问…

超过 37000 台 VMwareESXi 服务器可能受到持续攻击威胁

近日&#xff0c;威胁监测平台影子服务器基金会&#xff08;The Shadowserver Foundation&#xff09;发布报告&#xff0c;指出超 3.7 万个互联网暴露的威睿&#xff08;VMware&#xff09;ESXi 实例存在严重安全隐患&#xff0c;极易受到 CVE-2025-22224 漏洞的攻击。该漏洞属…

Linux《基础开发工具(中)》

在之前的Linux《基础开发工具&#xff08;上&#xff09;》当中已经了解了Linux当中到的两大基础的开发工具yum与vim&#xff1b;了解了在Linux当中如何进行软件的下载以及实现的基本原理、知道了编辑器vim的基本使用方式&#xff0c;那么接下来在本篇当中将接下去继续来了解另…

Vue3 Pinia 符合直觉的Vue.js状态管理库

Pinia 符合直觉的Vue.js状态管理库 什么时候使用Pinia 当两个关系非常远的组件&#xff0c;要传递参数时使用Pinia组件的公共参数使用Pinia

知识库Dify和cherry无法解析影印pdf word解决方案

近期收到大量读者反馈&#xff1a;上传pdf/图文PDF到Dify、Cherry Studio等知识库时&#xff0c;普遍存在格式错乱、图片丢失、表格失效三大痛点。 在试用的几款知识库中除了ragflow具备图片解析的能力外&#xff0c;其他的都只能解析文本。 如果想要解析扫描件&#xff0c…

Webservice创建

Webservice创建 服务端创建 3层架构 service注解&#xff08;commom模块&#xff09; serviceimpl&#xff08;server&#xff09; 服务端拦截器的编写 客户端拦截器 客户端调用服务端&#xff08;CXF代理&#xff09; 客户端调用服务端&#xff08;动态模式调用&a…

腾讯云低代码开发应用

创建客户端应用 如上所示&#xff0c;登录腾讯云微搭低代码业务控制台&#xff0c;开始搭建企业官网应用 如上所示&#xff0c;在腾讯云微搭低代码业务控制台中&#xff0c;开始创建企业官网应用 如上所示&#xff0c;在腾讯云微搭低代码业务控制台中&#xff0c;开始编辑企业官…

【Java开发指南 | 第三十四篇】IDEA没有Java Enterprise——解决方法

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 1、新建Java项目2、单击项目名&#xff0c;并连续按两次shift键3、在搜索栏搜索"添加框架支持"4、勾选Web应用程序5、最终界面6、添加Tomcat 1、新建Java项目 2、单击项目名&#xff0c;并连续按两次…

深度学习原理与Pytorch实战

深度学习原理与Pytorch实战 第2版 强化学习人工智能神经网络书籍 python动手学深度学习框架书 TransformerBERT图神经网络&#xff1a; 技术讲解 编辑推荐 1.基于PyTorch新版本&#xff0c;涵盖深度学习基础知识和前沿技术&#xff0c;由浅入深&#xff0c;通俗易懂&#xf…