初识typescript及数据类型
# TypeScript 是什么?
| 项目 | 说明 |
|---|---|
| 本质 | JavaScript 的 超集 |
| 作用 | 给 JS 增加 类型系统 |
| 运行时 | ❌ 不能直接运行,需要编译成 JS |
| 编译器 | tsc |
| 核心价值 | 类型安全 + IDE 智能提示 + 可维护性 |
一句话:
TS = 带类型的 JavaScript
# 一、TypeScript 解决什么问题
一句话:
TypeScript = JavaScript + 类型系统
# JS 的典型痛点
function sum(a, b) {
return a + b
}
sum(1, '2') // 🤯 运行时才发现是 "12"
1
2
3
4
5
2
3
4
5
# TS 的改进
function sum(a: number, b: number): number {
return a + b
}
sum(1, '2') // ❌ 编译期直接报错
1
2
3
4
5
2
3
4
5
TS 的核心价值
- ❌ 少踩坑(提前发现错误)
- 🧠 更好的代码提示 & 自动补全
- 🔧 重构更安全
- 📐 更适合大型项目(React / Vue3 / Node)
# 二、TypeScript 的基本使用方式
# 1️⃣ 安装 & 编译(了解即可)
npm install typescript -g
tsc index.ts
1
2
2
大多数前端项目里:
- Vite / Vue / React 已经 内置 TS 支持
- 你几乎不用手动跑
tsc
# 2️⃣ 常见内置工具类型(必须认识)
| 工具类型 | 作用 |
|---|---|
Partial<T> | 变可选 |
Required<T> | 变必选 |
Pick<T, K> | 取部分字段 |
Omit<T, K> | 排除字段 |
Record<K, T> | key-value 对象 |
type User = {
id: number
name: string
age: number
}
type UserBase = Pick<User, 'id' | 'name'>
1
2
3
4
5
6
7
2
3
4
5
6
7
# 三、基础类型(最重要)
- JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。
- 所有的原始数据类型都没有属性(property)
let name = 'hello ';
console.log(name.toUpperCase());
console.log((new String('hello ')).toUpperCase());
1
2
3
4
2
3
4
当调用基本数据类型方法的时候,JavaScript 会在原始数据类型和对象类型之间做一个迅速的强制性切换
let isOK: boolean = true; // 编译通过
let isOK: boolean = Boolean(1) // 编译通过
let isOK: boolean = new Boolean(1); // 编译失败 期望的 isOK 是一个原始数据类型
1
2
3
2
3
# 1️⃣ 原始类型
let a: number = 1
let b: string = 'hello'
let c: boolean = true
let d: null = null
let e: undefined = undefined
let id: symbol = Symbol("unique");
let bigNumber: bigint = 123n;
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2️⃣ 数组
let arr1: number[] = [1, 2, 3]
let arr2: Array<string> = ['a', 'b']
1
2
2
# 3️⃣ 元组(固定长度 + 固定类型)
let tuple: [string, number] = ['age', 18]
1
常用于:
useState- 返回固定结构的数据
| 元组 | 数组 |
|---|---|
| 每一项可以是不同的类型 | 每一项都是同一种类型 |
| 有预定义的长度 | 没有长度限制 |
| 用于表示一个固定的结构 | 用于表示一个列表 |
const animal:[string,number,boolean] = ['hello ',10,true];
1
# 4️⃣ 枚举(Enum)
enum Status {
Pending,
Success,
Error
}
let s: Status = Status.Success
// 普通枚举
enum Gender{
GIRL,
BOY
}
console.log(`李雷是${Gender.BOY}`);
console.log(`韩梅梅是${Gender.GIRL}`);
// 常数枚举
enum Week{
MONDAY=1,
TUESDAY=2
}
console.log(`今天是星期${Week.MONDAY}`);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- 常数枚举与普通枚举的区别是,常数枚举会在编译阶段被删除,并且不能包含计算成员。
- 假如包含了计算成员,则会在编译阶段报错
const enum Colors {
Red,
Yellow,
Blue
}
let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
const enum Color {Red, Yellow, Blue = "blue".length};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
📌 实战中 更推荐联合类型替代 enum(后面讲)
# 四、对象 & 接口(前端最常用)
# 1️⃣ 直接写对象类型
const user: {
name: string
age: number
} = {
name: 'Tom',
age: 18
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2️⃣ interface(强烈推荐)
interface User {
name: string
age: number
isAdmin?: boolean // 可选
}
const u: User = {
name: 'Tom',
age: 18
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
在 React props / Vue props / API 返回值 中大量使用
# 3️⃣ interface vs type(先记结论)
| 对比 | interface | type |
|---|---|---|
| 对象 | ✅ 强 | ✅ |
| 联合 | ❌ | ✅ |
| 扩展 | extends | & |
| React / Vue | 常用 | 常用 |
# 五、函数类型(前端必会)
- 可以指定参数的类型和返回值的类型
# 1️⃣ 参数 & 返回值
function add(a: number, b: number): number {
return a + b
}
1
2
3
2
3
没有返回值
let hello2 = function (name: string):void {
console.log('hello2', name);
return undefined;
}
hello2('hello ');
1
2
3
4
5
2
3
4
5
# 2️⃣ 可选参数 & 默认值
- 在TS中函数的形参和实参必须一样,不一样就要配置可选参数,而且必须是最后一个参数
function greet(name: string, age?: number) {} // age为可选参数
function greet2(name: string, age = 18) {} // age设置了默认值
1
2
2
# 可选参数
function print(name: string, age?: number):void {
console.log(name, age);
}
print('hahaha ');
1
2
3
4
2
3
4
# 默认参数
function ajax(url: string, method: string='GET') {
console.log(url, method);
}
ajax('/users');
1
2
3
4
2
3
4
# 3️⃣ 函数类型声明
定义函数类型
type GetUsernameFunction = (x: string, y: string)=>string;
let getUsername:GetUsernameFunction = function(firstName, lastName){
return firstName + lastName;
}
1
2
3
4
2
3
4
type Fn = (a: number, b: number) => number
const add: Fn = (a, b) => a + b
1
2
3
2
3
# 4️⃣ 剩余参数
function sum(...numbers:number[]) {
return numbers.reduce((val,item)=>val+=item,0);
}
console.log(sum(1,2,3));
1
2
3
4
2
3
4
# 5️⃣ 函数重载
- 在Java中的重载,指的是两个或者两个以上的同名函数,参数不一样
- 在TypeScript中,表现为给同一个函数提供多个函数类型定义
let obj: any = {};
function attr(val: string): void;
function attr(val: number): void;
function attr(val: any):void {
if (typeof val === 'string') {
obj.name = val;
} else {
obj.age = val;
}
}
attr('hahaha');
attr(9);
attr(true);
console.log(obj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 六、联合类型 & 类型别名(非常常用)
# 1️⃣ 联合类型(|)
- 联合类型(Union Types)表示取值可以为多种类型中的一种
- 未赋值时联合类型上只能访问两个类型共有的属性和方法
let name: string | number;
console.log(name.toString());
name = 3;
console.log(name.toFixed(2));
name = 'hello ';
console.log(name.length);
export {};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
let id: number | string
id = 1
id = '1'
1
2
3
4
2
3
4
# 2️⃣ type(类型别名)
type ID = number | string
type User = {
id: ID
name: string
}
1
2
3
4
5
6
2
3
4
5
6
# 七、any / unknown(一定要懂)
# 1️⃣ any(不推荐)
- any就是可以赋值给任意类型
- 第三方库没有提供类型文件时可以使用any
- 类型转换遇到困难时
- 数据结构太复杂难以定义
let a: any = 1
a.foo.bar() // TS 不管,运行时可能炸
1
2
2
let root:any=document.getElementById('root');
root.style.color='red';
1
2
2
let root:(HTMLElement|null)=document.getElementById('root');
root!.style.color='red';//非空断言操作符
1
2
2
# 2️⃣ unknown(安全版 any)
let x: unknown
if (typeof x === 'string') {
x.toUpperCase() // ✅
}
1
2
3
4
5
2
3
4
5
👉 经验法则
- 能不用
any就不用 - 接口数据不确定 →
unknown + 类型守卫
# 八、null 和 undefined
- null 和 undefined 是其它类型的子类型,可以赋值给其它类型,如数字类型,此时,赋值后的类型会变成 null 或 undefined
- strictNullChecks 参数用于新的严格空检查模式,在严格空检查模式下, null 和 undefined 值都不属于任何一个类型,它们只能赋值给自己这种类型或者 any
let x: number;
x = 1;
x = undefined;
x = null;
let y: number | null | undefined;
y = 1;
y = undefined;
y = null;
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 九、 void 类型
- void 表示没有任何类型
- 当一个函数没有返回值时,TS 会认为它的返回值是 void 类型。
function greeting(name:string):void {
console.log('hello',name);
//当我们声明一个变量类型是 void 的时候,它的非严格模式(strictNullChecks:false)下仅可以被赋值为 null 和 undefined
//严格模式(strictNullChecks:true)下只能返回undefined
//return null;
//return undefined;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 十、 特殊类型
# 1️⃣ never 类型
- 作为不会返回( return )的函数的返回值类型
// 返回never的函数 必须存在 无法达到( unreachable ) 的终点
function error(message: string): never {
throw new Error(message);
}
let result1 = error('hello');
// 由类型推论得到返回值为 never
function fail() {
return error("Something failed");
}
let result = fail();
// 返回never的函数 必须存在 无法达到( unreachable ) 的终点
function infiniteLoop(): never {
while (true) {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2️⃣ strictNullChecks
- 在 TS 中, null 和 undefined 是任何类型的有效值,所以无法正确地检测它们是否被错误地使用。于是 TS 引入了 --strictNullChecks 这一种检查模式
- 由于引入了 --strictNullChecks ,在这一模式下,null 和 undefined 能被检测到。所以 TS 需要一种新的底部类型( bottom type )。所以就引入了 never。
// Compiled with --strictNullChecks
function fn(x: number | string) {
if (typeof x === 'number') {
// x: number 类型
} else if (typeof x === 'string') {
// x: string 类型
} else {
// x: never 类型
// --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 3️⃣ never 和 void 的区别
- void 可以被赋值为 null 和 undefined的类型。 never 则是一个不包含值的类型。
- 拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。
# 十一、 Symbol
- 我们在使用 Symbol 的时候,必须添加 es6 的编译辅助库
- Symbol 是在ES2015之后成为新的原始类型,它通过 Symbol 构造函数创建
- Symbol 的值是唯一不变的
const sym1 = Symbol('key');
const sym2 = Symbol('key');
Symbol('key') === Symbol('key') // false
1
2
3
2
3
# 十二、 BigInt
- 使用 BigInt 可以安全地存储和操作大整数
- 我们在使用 BigInt 的时候,必须添加 ESNext 的编译辅助库
- 要使用1n需要 "target": "ESNext"
// number和 BigInt类型不一样,不兼容
const max = Number.MAX_SAFE_INTEGER;// 2**53-1
1
2
2
console.log(max + 1 === max + 2);
const max = BigInt(Number.MAX_SAFE_INTEGER);
1
2
2
console.log(max + 1n === max + 2n);
let foo: number;
let bar: bigint;
foo =bar;
bar = foo;
1
2
3
4
5
2
3
4
5
# 十三、类型推导(TS 的“智能”)
- 是指编程语言中能够自动推导出值的类型的能力,它是一些强静态类型语言中出现的特性
- 定义时未赋值就会推论成any类型
- 如果定义的时候就赋值就能利用到类型推论
let num = 1 // 推导为 number
let str = 'abc' // 推导为 string
1
2
2
函数返回值也能推导:
function add(a: number, b: number) {
return a + b // 自动推导 number
}
1
2
3
2
3
👉 写 TS 的正确姿势
- 能推导就不写
- 对外 API / 函数边界写清楚
# 十四、断言(你“比 TS 更清楚”)
- 类型断言可以将一个联合类型的变量,指定为一个更加具体的类型
- 不能将联合类型断言为不存在的类型
let name: string | number;
console.log((name as string).length);
console.log((name as number).toFixed(2));
console.log((name as boolean));
1
2
3
4
2
3
4
双重断言
interface Person {
name: string;
age: number;
}
const person = 'hello ' as any as Person; // ok
1
2
3
4
5
2
3
4
5
# 1️⃣ 类型推断(TS 的灵魂)
let num = 1 // 自动推断为 number
1
❗能不写就不写类型
# 2️⃣ 类型断言(as)
const img = document.querySelector('img') as HTMLImageElement
1
⚠️ 断言 ≠ 转换 只是告诉 TS「我比你清楚」
⚠️ 谨慎使用,断言 ≠ 类型检查
# 十五、字面量类型和类型字面量
- 字面量类型的要和实际的值的字面量一一对应,如果不一致就会报错
- 类型字面量和对象字面量的语法很相似
const up:'Up'= 'Up';
const down: "Down" = "Down";
const left: "Left" = "Left";
const right: "Right" = "Right";
type Direction = 'Up' | 'Down' | 'Left' | 'Right';
function move(direction: Direction) {}
move("Up");
1
2
3
4
5
6
7
2
3
4
5
6
7
type Person = {
name:string,
age:number
};
1
2
3
4
2
3
4
# 十六、字符串字面量 vs 联合类型
- 字符串字面量类型用来约束取值只能是某几个字符串中的一个, 联合类型(Union Types)表示取值可以为多种类型中的一种
- 字符串字面量 限定了使用该字面量的地方仅接受特定的值,联合类型 对于值并没有限定,仅仅限定值的类型需要保持一致
# 十七、TS 在前端框架中的典型用法
# React Props
interface Props {
title: string
count?: number
}
function MyComp({ title, count = 0 }: Props) {
return <div>{title} {count}</div>
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Vue3 + defineProps
interface Props {
msg: string
}
const props = defineProps<Props>()
1
2
3
4
5
2
3
4
5
# 十八、你下一步该学什么(路线建议)
# 🔹 第 1 阶段(你现在)
- 基础类型
- interface / type
- 联合类型
- 函数类型
- 类型推导
# 🔹 第 2 阶段(进阶必学)
- 泛型
<T> - keyof / typeof
- 映射类型
- 条件类型
- TS 在 React / Vue 中的最佳实践
# 🔹 第 3 阶段(高手)
- 写 类型工具
- 给组件库 / hooks 写类型
- 阅读 Vue / React 源码里的 TS
上次更新: 2026/01/07, 09:20:46