TypeScript 基础类型:从实战角度吃透它们
说实话,很多同学学 TypeScript 都是从基础类型开始的。但我在面试中见过不少人,背了八股文,真到写代码时却用不好。今天我就结合自己的项目经验,把这些基础类型掰开揉碎了讲清楚。
布尔、数字、字符串:最常用的三兄弟
这三个类型太基础了,但我还是想多说两句。你想想看,它们虽然简单,但用不好也会出问题。
// 布尔类型
let isDone: boolean = false;
let isActive: boolean = true;
// 数字类型
let age: number = 28;
let price: number = 99.9;
let hex: number = 0xf00d; // 十六进制
let binary: number = 0b1010; // 二进制
// 字符串类型
let name: string = "张三";
let greeting: string = `你好,${name}!`; // 模板字符串
嗯,这里要注意一点。JavaScript 里没有整数和浮点数的区分,TypeScript 也一样。所有数字都是浮点数。我在项目中遇到过有人纠结要不要用 int 类型,其实完全没必要。
数组:两种写法,一种选择
数组有两种定义方式。我个人更推荐第二种,尤其是在复杂类型场景下。
// 方式一:类型 + 方括号
let list1: number[] = [1, 2, 3];
// 方式二:泛型数组
let list2: Array<number> = [1, 2, 3];
// 实际项目中的例子
let userNames: string[] = ['张三', '李四', '王五'];
let userAges: number[] = [28, 32, 25];
元组:固定长度,固定类型
元组是 TypeScript 特有的类型。说白了,就是你知道数组里每个位置是什么类型。
// 定义一个元组
let user: [string, number] = ['张三', 28];
// 访问元组元素
console.log(user[0]); // 输出: 张三
console.log(user[1]); // 输出: 28
// 实际场景:返回多个值
function getUserInfo(): [string, number] {
return ['李四', 32];
}
我在项目中用元组最多的地方,就是处理 CSV 数据或坐标点。比如经纬度:[longitude, latitude],一眼就能看出哪个是经度哪个是纬度。
枚举:让代码更有语义
枚举是我在项目中用得比较多的类型。它能把数字和字符串映射成有意义的名称。
// 数字枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
// 字符串枚举
enum Status {
Success = 'SUCCESS',
Error = 'ERROR',
Pending = 'PENDING'
}
// 使用枚举
let dir: Direction = Direction.Up;
let status: Status = Status.Success;
我记得有一次重构一个老项目,里面全是 0、1、2 这样的魔法数字。我改成枚举后,代码可读性直接提升了一个档次。你想想看,if (status === Status.Success) 比 if (status === 0) 好理解多了吧?
type: ButtonType.Primary,比传字符串 'primary' 更安全。
any:双刃剑,慎用
any 类型是 TypeScript 的逃生舱。说白了,就是告诉编译器:别管我,我知道我在干什么。
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // 没问题,想怎么变就怎么变
// 实际场景:第三方库没有类型定义
let thirdPartyData: any = fetchSomeData();
void、null/undefined、never:边缘但重要
这几个类型平时用得不多,但关键时刻能救命。
// void:函数没有返回值
function logMessage(message: string): void {
console.log(message);
}
// null 和 undefined
let u: undefined = undefined;
let n: null = null;
// never:永远不会返回
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
嗯,这里要重点说说 never。我在项目中遇到过一种情况:一个函数根据条件抛出错误或无限循环,返回值类型就是 never。它告诉 TypeScript:这个函数不会正常结束。
类型推断:让 TypeScript 帮你干活
TypeScript 很聪明,很多时候你不用显式声明类型,它能自己推断出来。
let num = 10; // TypeScript 推断为 number
let str = "hello"; // 推断为 string
let isTrue = true; // 推断为 boolean
// 函数返回值推断
function add(a: number, b: number) {
return a + b; // 推断返回类型为 number
}
我个人习惯是:简单类型让 TypeScript 推断,复杂类型或函数参数显式声明。这样既省事又安全。
类型断言:告诉 TypeScript 你比它懂
有时候你比 TypeScript 更了解某个值的类型。这时候可以用类型断言。
// 方式一:尖括号语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
// 方式二:as 语法(推荐)
let someValue2: any = "this is a string";
let strLength2: number = (someValue2 as string).length;
总结一下
这些基础类型看着简单,但用好了能让你的代码质量提升一大截。我见过太多项目因为类型定义不规范,后期维护成本飙升。
记住几个原则:
- 能用具体类型就别用 any
- 能用枚举就别用魔法数字
- 能用元组就别用数组(当你知道长度时)
- 能用 unknown 就别用 any
好了,这一章就到这里。下一章我们会深入对象类型和接口,那才是 TypeScript 真正发力的地方。