一、简介
TypeScript 是 JavaScript 的超集,核心能力是 静态类型检查——在代码运行前强制校验变量/函数的类型,避免“类型不匹配”导致的运行时错误(如把数字当字符串拼接)。同时,类型标注能让代码成为“自文档”,他人阅读时无需追溯逻辑就能明确数据结构,大幅提升团队协作效率和代码可维护性。
TypeScript 的类型体系分为两类:
- JavaScript 原生基础类型:string、number、boolean、null、undefined、symbol、object(注意:数组、函数本质是 object 的子类型,但 TypeScript 提供了更具体的类型标注方式)。
- TypeScript 扩展类型:元组(Tuple)、枚举(enum)、any、void、never、unknown、字面量类型。
二、定义JavaScript基础类型
2.1 string
string类型用于表示文本数据,在TypeScript中,字符串可以使用单引号或双引号括起来,也可以使用模板字符串。
let str: string = 'Hello Word!';
let str2: string = `Hello Word!${str}`;
2.2 number
number类型用于表示数值,包括整数和浮点数。除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
let num: number = 100;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
2.3 boolean
boolean类型用于表示逻辑值,只有两个可能的取值:true和false。
let bool: boolean = true;
2.4 null和undefined
null和undefined类型分别表示空值和未定义值。
let nullVal: null = null;
let undefinedVal: undefined = undefined;
2.5 symbol
symbol类型用于创建唯一的标识符,通常用于对象的属性键。
let sym1: symbol = Symbol('userKey');
let sym2: symbol = Symbol('userKey');
console.log(sym1 === sym2); // 输出false,即使描述符相同,symbol实例也不相等
// 用symbol作为对象属性键,避免属性名冲突
const user = {
[sym1]: '张三', // 私有属性,外部无法通过常规字符串键访问
name: '公开名称'
};
console.log(user[sym1]); // 输出"张三"
console.log(user.name); // 输出"公开名称"
2.6 object
object
类型用于表示 非原始类型的“通用容器”(即除 string/number/boolean/null/undefined/symbol 外的类型),但 不推荐直接用 object
标注数组、函数或具体对象(应使用更精准的类型)。
// 仅表示“这是一个对象”,不关心内部属性
let obj: object = { name: "张三", age: 20 };
// 错误:不能用 object 标注数组(数组有更具体的类型 number[])
// let arr: object = [1, 2, 3];
// object类型用于表示非原始类型的值,包括数组、函数和对象。
2.7 array
array类型用于表示有序的元素集合,每个元素可以是任意类型。
let arr: number[] = [1, 2, 3];
let arr2: Array<number> = [4, 5, 6];
// 元素是对象的数组(常见于接口返回数据)
let userArr: Array<{ id: number; name: string }> = [
{ id: 1, name: "张三" },
{ id: 2, name: "李四" }
];
// 混合类型数组(如“[姓名, 年龄]”组成的数组)
let personArr: Array<[string, number]> = [["张三", 20], ["李四", 25]];
// 只读数组不能修改
let readonlyArr: readonly number[] = [1, 2, 3];
// 错误:
// readonlyArr.push(4);
// readonlyArr[0] = 0;
三、定义TypeScript特有类型
3.1 元组Tuple
元组是 固定长度、元素类型可不同 的“严格数组”,核心价值是“精确约束多值集合的结构”(如函数返回 [状态码, 数据]、坐标 [x, y])。
// 元组:第1个元素是 string,第2个是 number(长度必须为2)
let user: [string, number] = ["张三", 20];
// 正确:按索引访问,类型会自动推断
const name = user[0]; // name: string
const age = user[1]; // age: number
// 错误:长度不匹配 / 类型不匹配
// let wrongUser1: [string, number] = ["张三"]; // 长度少1
// let wrongUser2: [string, number] = [20, "张三"]; // 类型顺序错
// 元祖索引越界问题
let tuple: [string, number] = ["a", 1];
// 允许追加:类型必须是 string | number
tuple.push("b");
tuple.push(2);
// 错误:不能追加其他类型
// tuple.push(true);
// 注意:追加后元组长度仍视为“固定长度”(访问索引2会报错)
// console.log(tuple[2]); // 错误:索引2超出元组[0,1]的范围
3.2 枚举enum
枚举类型用于定义命名的常量集合,使代码更易读和维护。
enum Color {
Red,
Green,
Blue
}
// Red = 0, Green = 1, Blue = 2
let c: Color = Color.Green;
enum Color2 {
Red = 'red',
Green = 'green',
Blue = 'blue'
}
// Red = 'red', Green = 'green', Blue = 'blue'
let c2: Color2 = Color2.Blue;
3.3 any
any类型用于表示任意类型的值,通常在不确定类型的情况下使用。
let anyVal: any = 'Hello Word!';
3.4 void
void类型用于表示没有任何类型的值,通常用于函数没有返回值的情况。
function log(msg: string): void {
console.log(msg);
}
3.5 never
never类型用于表示永远不会发生的值,通常用于抛出异常或无限循环的情况。
function throwError(msg: string): never {
throw new Error(msg);
}
3.6 unknown
unknown 是 “安全版的 any”—— 同样表示 “未知类型”,但 不允许直接使用(需先做类型判断),既保留了灵活性,又避免了 any 的安全风险,是处理 “动态类型” 的推荐方案。
let unknownVal: unknown = 'Hello Word!';
if (typeof unknownVal === 'string') {
console.log(unknownVal.toUpperCase());
}
unknownVal = 100;
if (typeof unknownVal === 'number') {
console.log(unknownVal.toFixed(2));
}
3.7 字面量类型
字面量类型用于表示具体的字符串或数值,而不是通用的字符串或数值类型。
// 单一字面量类型
const strLiteral: 'hello' = 'hello';
const numLiteral: 100 = 100;
// 联合字面量类型
// 约束请求方法只能是 'GET' / 'POST' / 'PUT'
type HttpMethod = 'GET' | 'POST' | 'PUT';
// 函数参数只能是 HttpMethod 中的值
function request(method: HttpMethod, url: string) {
console.log(`用 ${method} 方法请求 ${url}`);
}
request('GET', '/api/users');
// 数字字面量联合类型
type StatusCode = 200 | 400 | 404 | 500;
let code: StatusCode = 200; // 正确
// code = 300; // 错误:300 不在 StatusCode 中
四、总结
TypeScript 基础类型是构建类型安全代码的核心,其设计逻辑围绕 “精准约束、提前避错、提升可读性” 展开。
从类型体系来看,可分为两类核心应用场景:
- JavaScript 原生类型的增强:string、number、boolean 等原生类型通过静态标注,避免 “类型隐式转换” 导致的运行时错误;array 提供了 “单一类型 / 复杂类型 / 只读” 的细粒度约束;object 则明确为 “非原始类型的通用容器”,但需优先使用更具体的子类型(如对象字面量、函数类型)提升精准度。
- TypeScript 扩展类型的价值:元组(Tuple)解决了 “固定结构多值集合” 的约束问题(如函数多返回值);枚举(enum)将分散的常量结构化,提升代码可维护性;any 作为 “兼容旧代码的临时方案”,需谨慎使用以避免失去类型检查优势;unknown 则通过 “类型收窄” 实现了动态类型的安全处理;never 标注 “不可能返回的函数”,完善了类型系统的完整性;字面量类型(尤其是联合字面量)则以轻量方式实现 “取值范围约束”,比枚举更灵活。
在实际开发中,选择类型的核心原则是 “能具体不模糊,能精确不通用”:优先用 string[] 而非 any[],用 unknown 而非 any,用联合字面量或枚举而非松散的 string—— 通过合理的类型标注,既能让 TypeScript 发挥静态检查的优势,也能让代码成为 “自文档”,降低团队协作成本。