前端开发入门指南Day 15:TypeScript入门 - 从JavaScript到TypeScript

为什么需要TypeScript? 🤔

JavaScript最初是为了在网页中添加简单的交互效果而设计的。但随着Web应用变得越来越复杂,我们用JavaScript构建的应用规模也越来越大:从简单的表单验证发展到完整的企业级应用。

想象一下,你正在建造一座大楼,如果你使用的是JavaScript,就像是在用积木搭建 - 虽然灵活,但当建筑变得复杂时,很容易出错。而TypeScript就像是给这些积木加上了榫卯结构(限定了每一块的作用) - 它能确保每块积木都正确地咬合在一起。

让我们通过一个简单的例子来理解这个问题:

// JavaScript中的常见问题
function calculateTotal(price, quantity) {return price * quantity;
}calculateTotal("10", 5);    // 结果: "101010..."
calculateTotal(true, "2");  // 结果: NaN

在JavaScript中,这段代码完全合法,但可能产生想不到的错误。现在看看TypeScript如何帮我们避免这个问题:

// TypeScript版本
function calculateTotal(price: number, quantity: number): number {return price * quantity;
}calculateTotal("10", 5);    // ❌ 编译错误:类型"string"的参数不能赋给类型"number"的参数
calculateTotal(true, "2");  // ❌ 编译错误:类型不匹配

TypeScript是JavaScript的超集 🎯

这句话经常被提到,但什么是"超集"呢?想象JavaScript是一个基础的工具箱,而TypeScript是一个升级版的工具箱 - 它包含了原来所有的工具(JavaScript的所有功能),还添加了新的工具(类型系统等)。

关键点:

  • 所有合法的JavaScript代码都是合法的TypeScript代码
  • TypeScript添加了可选的类型标注系统
  • TypeScript代码最终会被编译成JavaScript运行

TypeScript解决了什么问题? 🛠️

  1. 提前发现错误
interface UserData {firstName: string;lastName: string;age: number;email: string;parentEmail?: string; // 可选属性
}function processUserData(user: UserData) {const fullName = user.firstName + " " + user.lastName; // ✅ 确保属性存在const age = user.age;const email = user.email; // ✅ 明确的属性名if (age < 18) {// ✅ TypeScript会检查parentEmail是否存在sendParentalNotification(user.parentEmail);}
}// 所有这些错误在编写代码时就能被发现
processUserData({firstName: "John"}); // ❌ 错误:缺少必需的属性
processUserData({firstName: "John", lastName: "Doe", email: 123}); // ❌ 错误:类型不匹配
processUserData("Not an object"); // ❌ 错误:参数类型错误
  1. 更好的开发体验
// TypeScript提供智能提示
const user = {name: "Alice",age: 25
};user.  // 👈 在这里输入点号,IDE会提示所有可用的属性

     3 . 提升代码可维护性

// 定义一个清晰的API契约
interface PaymentProcessor {processPayment(amount: number): Promise<PaymentResult>;refund(transactionId: string): Promise<RefundResult>;getTransaction(id: string): Promise<TransactionDetails>;
}// 如果你需要修改接口
interface PaymentProcessor {processPayment(amount: number, currency: string): Promise<PaymentResult>; // 添加了currency参数
}// TypeScript会帮你找出所有需要更新的地方!
// 而在JavaScript中,你需要手动检查所有使用processPayment的地方

一个严重的生产环境bug需要4小时才能发现和修复。而如果使用TypeScript,这个bug在开发阶段就能被发现:

// 一个真实的例子:处理金融数据
interface Transaction {amount: number;currency: string;exchangeRate: number;
}function calculateTotal(transactions: Transaction[]): number {return transactions.reduce((total, t) => {// TypeScript会确保amount和exchangeRate都是数字return total + t.amount * t.exchangeRate;}, 0);
}// 如果没有TypeScript,这样的错误可能悄悄溜到生产环境
const badData = [{ amount: "1000", currency: "USD", exchangeRate: "1.2" }, // 字符串!{ amount: 500, currency: "EUR", exchangeRate: 1.1 }
];calculateTotal(badData); // TypeScript: ❌ 类型错误
// JavaScript: 🐛 悄悄产生错误的计算结果

这个深入的解释展示了为什么TypeScript在现代Web开发中变得越来越重要。它不仅仅是添加了类型标注,而是提供了一个完整的开发体验提升方案。

基础TypeScript类型详解 📚

基本类型

// 最常用的基本类型
let name: string = "Alice";              // 字符串
let age: number = 25;                    // 数字
let isStudent: boolean = true;           // 布尔值
let notFound: null = null;               // 空值
let notDefined: undefined = undefined;   // 未定义
let returnValue: void = undefined;       // 无返回值// 为什么需要这些类型?
// 1. 代码更容易理解 - 一眼就能看出变量的用途
// 2. 避免运行时错误 - 在编译时就能发现类型错误
// 3. 更好的IDE支持 - 准确的代码补全和提示

复合类型

// 数组 - 当我们需要处理同类型数据的集合
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob"];// 元组 - 固定长度和类型的数组
let user: [string, number] = ["Alice", 25];  // 精确定义每个位置的类型// 枚举 - 一组命名常量
enum Direction {Up = "UP",Down = "DOWN",Left = "LEFT",Right = "RIGHT"
}
let moveDirection: Direction = Direction.Up;

接口(Interface) - 定义对象的形状 📐

// 为什么需要接口?
// 想象接口是一个契约,定义对象必须具有的属性和方法interface User {name: string;age: number;email?: string;  // 可选属性用?标记sayHello(): void;
}// 实现接口
const alice: User = {name: "Alice",age: 25,sayHello() {console.log(`Hello, I'm ${this.name}`);}
};

类型别名(Type Alias) - 给类型起个新名字 ✏️

// 为什么需要类型别名?
// 1. 简化复杂类型的书写
// 2. 提高代码可读性
// 3. 实现类型复用type Point = {x: number;y: number;
};type ID = string | number;  // 联合类型// 使用类型别名
let coordinate: Point = { x: 10, y: 20 };
let userId: ID = "user123";  // 可以是字符串
userId = 123;                // 也可以是数字

类型断言 - 告诉编译器"相信我" 🤝

// 为什么需要类型断言?
// 有时候你比TypeScript更了解值的类型// 场景1: DOM操作
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;// 场景2: 对象转换
interface Cat {name: string;meow(): void;
}// 告诉编译器这个对象符合Cat接口
let kitty = {name: "Kitty",meow: () => console.log("Meow~")
} as Cat;

实战上手配置 💡

  1. 开始一个新项目时:
# 初始化TypeScript项目
npm init -y
npm install typescript --save-dev
npx tsc --init  # 生成tsconfig.json
  1. tsconfig.json关键配置:
{"compilerOptions": {"target": "es5",        // 编译目标版本"strict": true,         // 启用所有严格类型检查"outDir": "./dist",     // 输出目录"rootDir": "./src"      // 源码目录}
}

学习建议 📝

  1. 先掌握基础类型,它们是最常用的
  2. 理解接口的概念,它是TypeScript中最重要的特性之一
  3. 多看错误提示,它们能帮助你理解类型系统

通过这篇文章,你应该对TypeScript有了基本的认识。记住,TypeScript的目的是帮助我们写出更可靠的代码,而不是增加开发负担。在实践中,你会发现类型系统带来的好处远超过学习它所需的时间投入。

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

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

相关文章

rockit 学习、开发笔记(五)(VDEC)

前言 后面由于业务需求有rockit编解码的功能开发&#xff0c;这里我是第一次接触编解码&#xff0c;所以后续有些概念表述可能不太清楚&#xff0c;请各位多多包涵。 先来说一下解码模块的使用&#xff0c;rockit中的解码模块是VDEC&#xff0c;如果想要开发rockit的vdec可能…

unicloud微信小程序云端一体项目DEMO

最近应客户需求&#xff0c;做了一个产品展示的云开发小程序&#xff0c;从了解云开发到应用到实际项目的产品demo&#xff0c;希望大家能从中获取到对自己有用的东西。 说下心得体会吧&#xff0c;一般小项目用这种云开发确实会减少很多开发成本&#xff0c;人力成本&#xf…

图的创建和基础操作(数据结构实验作业)

上面是我的实验作业要求&#xff1a;&#xff08;看不到的同学&#xff0c;移步&#xff1a;https://gitee.com/young-lion/picture-bed/raw/master/202412051939715.png&#xff09; 下面的代码使用的是go语言&#xff1a; package mainimport ("fmt" )// 访问标记…

flex布局容易忽略的角色作用

目录 清除浮动 作用于行内元素 flex-basis宽度 案例一&#xff1a; 案例二&#xff1a; 案例三&#xff1a; flex-grow设置权重 案例一&#xff1a; 案例二&#xff1a; 简写flex-grow:1 0 auto; flex作为一维布局,行和列的使用&#xff0c;忽略的小角色&#xff0c;大…

javascript-svg-在圆环上拖动并选中区域

目录 问题描述解决思路代码结构 问题描述 假设我某个页面上使用了<svg>&#xff0c;其中包括一个<circle>。我希望实现的是&#xff1a;在circle上点击某个位置后&#xff0c;拖动&#xff0c;出现圆弧状阴影。实现效果为&#xff1a; 解决思路 要实现这个效果…

Android 使用 Canvas 和 Paint 实现圆形图片

学习笔记 效果展示: 全部代码: public class YuanActivity extends AppCompatActivity {private ActivityYuanBinding binding;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 通过 DataBinding 获取布局文件binding …

python怎么将字母大写

Python中有三种将字母转换为大写的方法&#xff1a;upper()、capitalize()、title()。 下面通过实例给大家介绍具体用法&#xff1a; str "www.php.com" print(str.upper()) # 把所有字符中的小写字母转换成大写字母 print(str.lower()) # 把所有字…

鸿蒙Next星河版高级用例之网络请求和自适应布局以及响应式布局

目录&#xff1a; 1、发起网络请求的两种方式第一种使用httpRequest发送http的请求&#xff1a;1.1、在进行网络请求前&#xff0c;您需要在module.json5文件中申明网络访问权限1.2、GET 请求1.3、POST请求1.4、处理响应的结果第二种使用axios发送http的请求&#xff1a;1.1、在…

ClouderaManager 集群搭建

前提&#xff1a;服务器之前做过域名映射、免密登录 ClouderaManager 集群 1. 组件分布规划 服务器服务器h1zk、hdfs(dn)、yarn(nm)、spark、kafka、flumeh2hdfs(nn-standy)、yarn(rm-active)、sparkh3hdfs(nn-active)、yarn(rm-standy)、hive、sparkh4zk、hdfs(dn)、yarn(n…

如何获取谷歌新闻API密钥?

在信息获取和新闻传播领域&#xff0c;快速获取最新的新闻动态至关重要。谷歌新闻API为开发者提供了强大的工具&#xff0c;能够方便地集成全球各类新闻内容。通过使用该API&#xff0c;开发者可以实现对新闻的实时访问和管理&#xff0c;为用户提供丰富的信息服务。本文将指导…

IP 协议

IP协议 一、介绍1、IP协议2、IPv43、IPv6 二、主要功能三、协议格式1、示意图2、说明 四、网段划分1、介绍2、目的3、方法4、步骤 五、基于类别的IP地址分配方式1、示意图2、范围 六、CIDR1、介绍2、组成3、优点4、示意图 七、子网掩码1、介绍2、功能3、表示方法4、CIDR表示法5…

数据结构 (23)并查集与等价类划分

一、并查集 并查集&#xff08;Union-Find Set或Disjoint Set&#xff09;是一种数据结构&#xff0c;用于处理一些不相交集合&#xff08;disjoint sets&#xff09;的合并及查询问题。它通常表示为森林&#xff0c;并用数组来实现&#xff08;类似于二叉堆&#xff09;。在并…

Java 【数据结构】 哈希(Hash超详解)HashSetHashMap【神装】

登神长阶 第十神装 HashSet 第十一神装 HashMap 目录 &#x1f454;一.哈希 &#x1f9e5;1.概念 &#x1fa73;2.Object类的hashCode()方法: &#x1f45a;3.String类的哈希码: &#x1f460;4.注意事项: &#x1f3b7;二.哈希桶 &#x1fa97;1.哈希桶原理 &#x…

lyapunov指数的绘制

有如下方程&#xff1a; %% 方程式 % x(n1)1y(n)-a*x(n)^2 % y(n1)b*x(n)绘制其对应的lyapunov指数。 MATLAB实现方式&#xff1a; clc; clearvars; close all;%% 方程式 % x(n1)1y(n)-a*x(n)^2 % y(n1)b*x(n)%% 代码 N 1000; a (0:0.001:1.4); b 0.3; na length(a…

LearnOpenGL学习(高级OpenGL -- 深度测试,模板测试,)

深度测试 深度缓冲用来防止被阻挡的面渲染到其他面的前面&#xff0c;深度缓冲就像颜色缓冲&#xff0c;在每个片段中储存了信息&#xff0c; 当深度测试(Depth Testing)被启用的时候&#xff0c;OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测…

【CSP CCF记录】202305-2第30次认证 矩阵运算

题目 样例输入 3 2 1 2 3 4 5 6 10 10 -20 -20 30 30 6 5 4 3 2 1 4 0 -5 样例输出 480 240 0 0 -2200 -1100 思路 我的初步想法是按照题目所给计算顺序&#xff0c;分为三步计算&#xff0c;即&#xff1a; 1. &#xff0c;时间复杂度为 2. &#xff0c;时间复杂度为 3.&a…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

书生实战营第四期-进阶岛第一关-探索 InternLM 模型能力边界

任务一: InternThinker 挑战 Leetcode Leetcode题目链接 Prompt InternThinker 回答截图 Q1 仅含置位位的最小整数 - 力扣&#xff08;LeetCode&#xff09; 给你一个正整数 n。 返回 大于等于 n 且二进制表示仅包含 置位 位…

[SAP ABAP] ALV基础开发

ALV全称为SAP List Viewer&#xff0c;是SAP中常用的报表输出格式&#xff0c;输出结果以行和列展示&#xff0c;集成的功能有排序&#xff0c;求和&#xff0c;过滤&#xff0c;隐藏&#xff0c;筛选等功能 ALV格式的数据是以单元格为单位显示&#xff0c;这种方式便于数据导…

360全向触觉型灵巧手 Allegro Hand V5 亮相,Wonik 机器人助推前沿科技前行

在机器人技术持续演进的当下&#xff0c;Wonik Robotics 依靠自身技术实力&#xff0c;推出了新一代机器人手 Allegro Hand V5&#xff0c;为工业与科研领域带来新机遇。 Allegro Hand V5 具备诸多出色特性。 Allegro Hand V5 指尖配备的全方位触觉传感器是一大亮点&#xff0…