在刚开始接触使用TS时,不像单纯写JS代码那样方便,常常要加类型声明,有时还要去查文档,而且时不时会提前报错,觉得麻烦极了,但是我读了官方文档,发现TS虽然麻烦但却十分重要,我们在学习一个新知识时,应该先了解这个知识为什么存在,是为了解决什么问题,,,
一.什么是 TypeScript?
TypeScript 是 JavaScript 的一个超集(superset),它在 JS 的基础上加入了静态类型系统,主要作用是:
-
编写时类型检查,提前发现错误
-
更强的开发工具支持(自动补全、跳转)
-
更适合大型项目开发
最终 TS 会被编译(transpile)成标准 JavaScript 来运行。
安装
npm install -g typescript
编译运行
tsc hello.ts # 编译为 hello.js
二.TS为什么存在?
TypeScript(TS)存在的根本原因可以用一句话总结:
JavaScript 太灵活,写得爽但维护难,TypeScript 用类型系统来增强 JavaScript 的可维护性和可靠性。
背后的核心原因:
JavaScript 是弱类型语言,容易出错
JS 写起来快,但常见的问题包括:
-
变量类型混乱
-
函数参数传错不报错
-
对象结构不一致
-
编译期(开发时)看不出错,运行时才炸
TypeScript 加入静态类型系统,在写代码时就能发现这些问题。
TypeScript 存在的意义是:给 JavaScript 加上“类型 + 智能 + 规范”,让前端开发更严谨、更高效、更可维护。
三.TS的基础内容
(一)TS基本类型
let num: number = 42;
let str: string = "hello";
let bool: boolean = true;
let undef: undefined = undefined;
let nul: null = null;
let anyVar: any = "can be anything";
let unknownVar: unknown = "safe version of any";
特别类型:
类型 | 描述 |
any | 任意类型(不推荐使用) |
unknown | 安全的任意类型,必须类型检查后使用 |
never | 永远不会返回(如抛错的函数) |
重点介绍一下unknown和never:
1.unknown:
unknown
是“更安全”的 any
,它让你不能直接使用它的值,必须检查或断言后才能用,这就可以在不牺牲灵活性的前提下,提高代码的安全性和可维护性。
你不能直接使用unknown:
let value: unknown = "hello";
value.toUpperCase(); // 这里会报错
而是判断之后或者加断言在可以正常使用
let value: unknown = "hello";
if (typeof value === "string") {
// 这里 TS 确认 value 是 string 类型
console.log(value.toUpperCase()); // ✅ OK
}
/////////////////////////////////////
如果你确信它是什么类型,可以用 as 告诉 TypeScript:“我保证它是某个类型”。
let value: unknown = "hello";
console.log( (value as string).toUpperCase() ); // ✅ OK
注意:类型断言是你自己负责风险,如果断错了,运行时会报错
2.never:
never
表示一个值永远不会出现。
具体来说,一个返回 never
的函数永远不会结束,或者永远不会返回
function throwError(message: string): never {
throw new Error(message);
}
.............................................
function infiniteLoop(): never {
while (true) {}
}
(二)数组、元组、枚举
数组
let nums: number[] = [1, 2, 3]; let strs: Array<string> = ["a", "b"];
元组(Tuple)
元组可以看作是长度固定、类型固定的数组。
数组与元组的区别,简单理解:
数组 是“元素类型相同、长度不固定”的集合;
元组 是“每个元素位置的类型都预先定义、长度固定”的结构化数据。
let tuple: [string, number] = ["age", 30];
枚举(Enum):就是把一组有名字的常量值组织在一起,形成一个有意义的“集合类型”。
//默认里面是数字类型
enum Direction {
Up, //number
Down, //number
Left, //number
Right,//number
}
let dir: Direction = Direction.Up;
.....................................
//设置为字符串型枚举
enum Direction {
Up='up', //string
Down='down', //string
Left='left', //string
Right='right',//string
}
枚举的默认类型行为
枚举类型 | 默认行为 | 值类型 | |
---|---|---|---|
数字枚举 | 默认从 0 开始编号(可改) | number | |
字符串枚举 | 每个成员都要手动赋字符串 | string | |
异构枚举 | 同时包含数字和字符串(不推荐) | 混合类型 |
(三)类型注解 与 类型推导
1. 显式类型注解
这是 TypeScript 的核心特性之一:你可以为变量、参数、返回值显式指定类型。
let age: number = 25;
let name: string = "Tom";
let isAdmin: boolean = true;
function greet(name: string): string {
return `Hello, ${name}`;
}
2.类型推导
在大多数情况下会自动推断变量的类型,你可以不写类型,它也知道该怎么检查
let score = 99; // 推断为 number
let username = "Jack"; // 推断为 string
function double(n = 2) {
return n * 2; // 推断参数 n 是 number,返回值也是 number
}
那什么时候需要写类型,什么时候不需要?
场景 | 是否建议写类型注解 |
---|---|
变量赋值时能清楚看到类型 | 可省略,TS 会推断 |
函数参数和返回值 | 建议写明类型 |
复杂结构(对象、数组) | 推荐写注解 |
(四)对象类型(接口 & 类型别名)
一、接口(interface
)
属性
-
可选属性:
?
-
只读属性:
readonly
-
继承(扩展):
extends
interface Person {
name: string;
age: number;
readonly id: string;
gender?: string; // 可选属性
}
interface Student extends Person {
school: string;
}
二、类型别名(type)
定义联合类型
type Status = "success" | "error" | "loading";
let s1: Status = "success"; //
let s2: Status = "error"; //
let s3: Status = "pending"; // 报错:不是 Status 类型之一
定义联合对象结构
type Admin = { role: "admin"; perms: string[] };
type Guest = { role: "guest"; reason: string };
type User = Admin | Guest;
User
可以是 Admin
或 Guest,以下是使用的例子
function handleUser(user: User) {
if (user.role === "admin") {
console.log("管理员权限:", user.perms.join(", "));
} else {
console.log("访客原因:", user.reason);
}
}
定义函数签名
给函数定义一个固定格式,使其可以复用
type Add = (a: number, b: number) => number;
你可以用这个类型别名来声明多个函数变量:
const add: Add = (x, y) => x + y;
const multiply: Add = (x, y) => x * y;
使用例子
function compute(fn: Add, a: number, b: number): number {
return fn(a, b);
}
compute(add, 3, 5); // 8
compute(multiply, 3, 5); // 15
总结不易,点个赞吧!