TypeScript 基础(上):基础类型与接口
好,咱们开始进入 TypeScript 的核心部分。说实话,很多同学学 TypeScript 容易卡在「类型体操」上,但我觉得,先把基础类型和接口玩明白,日常开发就够用了。今天这一章,我带你把这些基础打扎实。
基础类型:number、string、boolean、array、object
TypeScript 的基础类型,说白了就是给 JavaScript 的值加了个「标签」。你想想看,JS 里一个变量可以是数字、字符串、对象,但到底是个啥,得运行了才知道。TypeScript 就是要让这些信息在写代码的时候就明确下来。
number、string、boolean
这三个是最常用的基础类型。写法很简单:
let age: number = 28;
let name: string = '张三';
let isActive: boolean = true;
嗯,这里要注意:number 不区分整数和浮点数,所有数字都是 number 类型。我在项目中遇到过有人写 let count: int = 5,结果 TypeScript 直接报错——没有 int 类型,只有 number。
let age = 28,它就知道 age 是 number 类型。
array 数组
数组有两种写法,我个人习惯用第一种:
// 写法一:推荐
let list: number[] = [1, 2, 3];
// 写法二:泛型写法
let list2: Array<number> = [1, 2, 3];
为什么推荐第一种?因为更直观。你一眼就能看出这是个数字数组。第二种在 JSX 里容易和 HTML 标签混淆,我踩过这个坑。
object 对象类型
对象类型稍微复杂一点。你不能只写 let obj: object = {},这样 TypeScript 只知道它是一个对象,但不知道里面有什么属性。正确的做法是:
let user: { name: string; age: number } = {
name: '李四',
age: 25
};
但说实话,这种写法在项目中很少直接用。因为一旦对象结构复杂了,代码会变得又长又丑。这时候就需要接口(interface)出场了。
类型注解与类型推断
这两个概念是 TypeScript 的基石。我简单解释一下:
- 类型注解:你主动告诉 TypeScript 某个变量是什么类型。
- 类型推断:TypeScript 根据赋值自动推导出类型。
举个例子:
// 类型注解
let count: number = 10;
// 类型推断
let count2 = 10; // TypeScript 自动推断为 number
我个人建议:能用推断的就别写注解。比如 let count = 10 已经很清楚是数字了,再加 : number 就是画蛇添足。但函数参数和返回值,我建议显式注解,因为这是「接口契约」,别人调用你的函数时能一眼看懂。
我曾经在团队里推行过「能不写就不写」的原则,结果代码 review 时发现有人把 let x: any = 'hello' 写得到处都是。any 类型会关闭类型检查,说白了就是「自废武功」。所以,尽量避免 any。
接口(interface)的基本使用
接口是 TypeScript 里我最喜欢的功能之一。它就像一份「合同」,规定了对象应该长什么样。
定义接口
interface User {
name: string;
age: number;
email?: string; // 可选属性
readonly id: number; // 只读属性
}
这里我解释一下:
email?表示这个属性可有可无。我在项目中经常用可选属性来处理「有些字段不一定有」的情况。readonly id表示这个属性只能在创建时赋值,之后不能修改。比如用户 ID,一旦创建就不应该变。
使用接口
function greet(user: User): string {
return `你好,${user.name}!`;
}
const newUser: User = {
name: '王五',
age: 30,
id: 1001
};
console.log(greet(newUser)); // 输出:你好,王五!
你想想看,如果没有接口,这个函数参数的类型得写成 { name: string; age: number; email?: string; readonly id: number },多长啊。用接口一封装,代码瞬间清爽了。
types.ts 文件里,管理起来方便多了。建议你也这么做。
接口的扩展
接口可以继承,就像类一样:
interface Admin extends User {
role: 'admin' | 'superadmin';
permissions: string[];
}
const adminUser: Admin = {
name: '赵六',
age: 35,
id: 2001,
role: 'admin',
permissions: ['read', 'write', 'delete']
};
这样,Admin 就拥有了 User 的所有属性,还多了自己的专属属性。我在做后台管理系统时,经常用这种方式来区分普通用户和管理员。
类型 vs 接口:什么时候用哪个?
很多新手会纠结这个问题。我直接给你一个实用建议:
| 场景 | 推荐用 | 原因 |
|---|---|---|
| 定义对象结构 | interface | 更直观,支持扩展 |
| 定义联合类型或交叉类型 | type | type 更灵活 |
| 定义函数类型 | type | 写法更简洁 |
| 需要合并声明 | interface | interface 支持声明合并 |
说白了,能用 interface 就用 interface,搞不定的时候再上 type。这是我在实际项目中总结出来的经验。
小结
这一章我们聊了 TypeScript 的基础类型、类型注解与推断,还有接口的基本使用。记住几个关键点:
- 基础类型要记牢,但别过度注解
- 接口是定义对象结构的利器
- 能用 interface 就别用 type(大部分情况)
- 避免 any,保持类型安全
下一章我们会深入接口的高级用法,比如泛型接口、接口与类的结合。到时候你会发现,TypeScript 的类型系统比想象中强大得多。
Product 接口,包含 id、name、price、description(可选)、category(只读)。然后写一个函数,接收 Product 类型参数,返回格式化后的商品信息字符串。
好,今天就到这里。有什么问题欢迎在评论区交流,咱们下章见。