TypeScript 中的类型有哪些?请列举。

TypeScript 中的类型有哪些?请列举。

大白话 TypeScript 中的类型有哪些?请列举。

前端小伙伴们,有没有被"类型错误"搞到抓头发过?写个函数传参,把number写成string,运行时才报错;定义对象少了个属性,测试时页面直接白屏……今天咱们就盘一盘TypeScript的"类型家族",从基础到高级,用最接地气的话讲清每种类型的作用,看完这篇,你不仅能叫出所有类型的名字,还能和面试官唠明白它们的使用场景~

一、"类型盲写"的痛与救

先讲个我上周踩的坑:给客户做表单验证组件,定义了一个validateUser函数,预期接收{ name: string; age: number }类型的参数。结果同事传了个age: "25"(字符串),页面直接报NaN错误。要是用了TypeScript,编辑器会红色波浪线警告,提前避免这种低级错误!

这种"类型盲写"的痛点,本质是JavaScript的"弱类型"特性——变量类型可以随意变,代码量大时根本记不住每个变量该是什么类型。而TypeScript的类型系统就是来当"代码安检员"的:写代码时就检查类型错误,把问题消灭在萌芽阶段。

二、TypeScript类型的"家族树"

TypeScript的类型系统像一棵枝叶繁茂的树,根是"基础类型",向上生长出"复合类型",再衍生出"高级类型"。咱们按层级逐个拆解:

1. 基础类型:最常用的"原子类型"

基础类型是TypeScript类型系统的"地基",对应JavaScript的原始类型+几个扩展类型,特点是不可再拆分。

类型名描述示例string字符串类型(单/双引号或模板字符串)const name: string = "张三";number数字类型(整数、浮点数、NaN、Infinity等)const age: number = 25;boolean布尔类型(true或false)const isVip: boolean = true;null空值(表示"没有值",只能赋值给null类型)const empty: null = null;undefined未定义(变量声明但未赋值时的默认值)const unassigned: undefined = undefined;symbol唯一且不可变的标识符(ES6新增,用于对象属性键)const key: symbol = Symbol("unique");bigint大整数类型(超过Number.MAX_SAFE_INTEGER的整数,用n后缀)const largeNum: bigint = 100000000000000000000n;void“无类型”(通常用于函数无返回值)function log(): void { console.log("hi"); }never“永不存在的值”(函数永远不会结束或抛出异常)function error(msg: string): never { throw new Error(msg); }2. 复合类型:基础类型的"组合体"

复合类型由基础类型或其他复合类型组合而成,描述更复杂的数据结构,常见的有:

(1)数组类型

描述"同类型元素的集合",有两种写法:

类型[](如number[]表示数字数组);Array<类型>(如Array表示字符串数组)。

// 数字数组(两种写法等价)

const nums1: number[] = [1, 2, 3];

const nums2: Array = [4, 5, 6];

// 对象数组(每个元素是{ name: string }类型)

const users: { name: string }[] = [

{ name: "张三" },

{ name: "李四" }

];

(2)元组(Tuple)

描述"固定长度、类型确定的数组",元素类型可以不同(和数组的区别:长度和类型固定)。

// 元组:[字符串, 数字, 布尔]

const person: [string, number, boolean] = ["张三", 25, true];

person[0] = "李四"; // 正确(string类型)

person[1] = "25"; // 错误(不能将string赋给number)

(3)对象类型

描述"键值对集合",明确每个属性的类型(可选属性用?标记,只读属性用readonly)。

// 对象类型(包含可选属性和只读属性)

type User = {

name: string; // 必选属性(string类型)

age?: number; // 可选属性(number类型,可不存在)

readonly id: number; // 只读属性(赋值后不可修改)

};

const user: User = {

name: "张三",

id: 1001

};

user.age = 25; // 正确(可选属性赋值)

user.id = 1002; // 错误(只读属性不可修改)

(4)枚举(Enum)

为一组数值或字符串值赋予友好的名字(解决"魔法数字"问题,比如用Status.Enable代替1)。

// 数字枚举(自动赋值,第一个成员默认0,后续递增)

enum Status {

Disable, // 0

Enable, // 1

Deleted // 2

}

console.log(Status.Enable); // 输出:1

// 字符串枚举(每个成员必须手动赋值)

enum Direction {

Up = "UP",

Down = "DOWN",

Left = "LEFT",

Right = "RIGHT"

}

console.log(Direction.Left); // 输出:"LEFT"

3. 高级类型:类型系统的"魔法工具"

高级类型是TypeScript的"进阶武器",可以动态生成新类型,解决复杂场景的类型约束问题。

(1)类型别名(Type Alias)

给类型起一个别名,简化复杂类型的使用(用type关键字定义)。

// 为对象类型起别名

type Point = { x: number; y: number };

const p: Point = { x: 10, y: 20 };

// 为联合类型起别名(后面会讲)

type ID = number | string;

const userId: ID = "1001"; // 可以是number或string

(2)接口(Interface)

描述对象的结构(和类型别名类似,但更侧重"行为约定",常用于面向对象设计)。

// 接口定义"可打印"行为

interface Printable {

content: string;

print(): void; // 方法(无具体实现)

}

// 类实现接口(必须包含content属性和print方法)

class Document implements Printable {

content: string;

constructor(content: string) {

this.content = content;

}

print() {

console.log(this.content);

}

}

(3)联合类型(Union Type)

表示"可以是多种类型中的一种"(用|分隔,解决"参数可以是A或B"的场景)。

// 函数参数可以是number或string(联合类型)

function formatID(id: number | string): string {

return id.toString(); // 安全操作(number和string都有toString方法)

}

formatID(1001); // 正确

formatID("1001"); // 正确

(4)交叉类型(Intersection Type)

表示"多种类型的交集"(用&合并,解决"同时具备A和B属性"的场景)。

// 定义"用户"和"权限"类型

type User = { name: string };

type Permission = { role: "admin" | "user" };

// 交叉类型:同时具备User和Permission的属性

type AdminUser = User & Permission;

const admin: AdminUser = {

name: "管理员",

role: "admin"

};

(5)泛型(Generic)

定义"类型模板",让组件支持多种类型(解决"函数/类/接口能处理不同类型"的问题)。

// 泛型函数:返回传入的值(保持类型)

function identity(arg: T): T {

return arg;

}

const num: number = identity(123); // T推断为number

const str: string = identity("abc"); // T推断为string

// 泛型接口:定义"容器"类型

interface Container {

value: T;

getValue(): T;

}

const stringContainer: Container = {

value: "hello",

getValue() { return this.value; }

};

(6)条件类型(Conditional Type)

根据类型关系动态选择类型(用T extends U ? X : Y语法,类似JS的三元表达式)。

// 条件类型:判断是否是数组类型

type IsArray = T extends any[] ? "是数组" : "不是数组";

type A = IsArray; // "是数组"

type B = IsArray; // "不是数组"

(7)类型断言(Type Assertion)

告诉编译器"我知道这个值的类型,相信我"(解决编译器无法推断类型的场景,用as或<>语法)。

// 从DOM获取元素(编译器无法确定具体类型)

const el = document.getElementById("app");

const divEl = el as HTMLDivElement; // 断言为HTMLDivElement类型

divEl.style.color = "red"; // 可以访问div特有的style属性

(8)类型守卫(Type Guard)

在运行时检查类型,缩小类型范围(用typeof/instanceof/自定义函数,解决联合类型的细分问题)。

// 联合类型:string或number

function printValue(value: string | number) {

// typeof类型守卫(缩小为string)

if (typeof value === "string") {

console.log("字符串长度:", value.length);

}

// typeof类型守卫(缩小为number)

if (typeof value === "number") {

console.log("数字平方:", value * value);

}

}

三、一张表理清类型分类

类型大类子类型核心特点典型场景基础类型string/number等不可再拆分,对应JS原始类型+扩展类型变量、函数参数的基础类型约束复合类型数组/元组/对象/枚举由基础类型组合而成,描述复杂数据结构列表数据、固定格式数据、状态标记高级类型类型别名/接口/联合等动态生成类型,解决复杂场景的类型约束通用组件、类型逻辑判断、类型收缩四、面试题回答方法

正常回答(结构化):

“TypeScript的类型可分为三大类:

基础类型:包括string、number、boolean、null、undefined、symbol、bigint、void、never,对应JavaScript的原始类型和扩展类型;复合类型:由基础类型组合而成,如数组(number[])、元组([string, number])、对象({ name: string })、枚举(enum);高级类型:动态生成类型的工具,如类型别名(type)、接口(interface)、联合类型(A | B)、交叉类型(A & B)、泛型(T)、条件类型(T extends U ? X : Y)、类型断言(as)、类型守卫(typeof)等。”

大白话回答(接地气):

“TypeScript的类型就像咱们整理衣柜——

基础类型是‘单件衣服’:T恤(string)、裤子(number)、袜子(boolean),都是最基础的单品;复合类型是‘搭配套装’:运动套装(数组,同类型元素)、礼服套装(元组,固定类型和数量)、带标签的盒子(对象,键值对);高级类型是‘魔法衣模’:可以按需求调整大小的万能衣架(泛型)、判断衣服类型的小镜子(类型守卫)、把两件衣服拼成新款式的缝纫机(交叉类型)。”

五、总结:3个使用原则+2个避坑指南

3个使用原则:

基础类型优先:变量、参数的基础类型约束用基础类型(如name: string);复合类型描述结构:复杂数据(如对象、列表)用复合类型(如User[]、[string, number]);高级类型解决复杂问题:通用组件用泛型,类型判断用条件类型,类型收缩用类型守卫。

2个避坑指南:

避免过度使用any:any会关闭类型检查(回到JS的"弱类型"模式),除非万不得已(如兼容旧代码),否则不要用;

错误示例:

const data: any = fetchData(); // 放弃类型检查,可能引入错误

接口和类型别名选对场景:

描述对象结构/行为约定(如类实现)→ 用接口(interface);定义联合/交叉类型、简化复杂类型→ 用类型别名(type)。

六、扩展思考:4个高频问题解答

问题1:interface和type有什么区别?

解答:

扩展方式:接口可以继承(extends),类型别名不能(但可以通过交叉类型&模拟);重复声明:接口可以重复声明(合并属性),类型别名不能(重复声明报错);使用场景:接口更适合描述对象的结构和行为(如类实现),类型别名更灵活(支持联合、交叉等)。

示例(接口合并):

interface User { name: string }

interface User { age: number } // 合并为{ name: string; age: number }

const user: User = { name: "张三", age: 25 }; // 正确

问题2:never和void有什么区别?

解答:

void表示"没有返回值"(函数可能返回undefined);never表示"永远不会结束"(函数抛出异常或无限循环)。

示例:

function log(): void {

console.log("hi");

// 返回undefined(隐式)

}

function error(msg: string): never {

throw new Error(msg);

// 永远不会执行到这里

}

问题3:泛型T和any有什么区别?

解答:

any会关闭类型检查(类型不安全);泛型T保留类型信息(类型安全),编译器会推断具体类型。

示例:

// any版本(类型不安全)

function identityAny(arg: any): any {

return arg;

}

const num = identityAny("123"); // num类型是any,无法保证是number

// 泛型版本(类型安全)

function identityGeneric(arg: T): T {

return arg;

}

const str = identityGeneric("123"); // str类型是string(编译器推断)

问题4:类型断言和类型转换有什么区别?

解答:

类型断言:仅告诉编译器"相信我,这个值是XX类型"(不改变运行时行为);类型转换(JS的Number()/String()):实际改变值的类型(影响运行时)。

示例:

// 类型断言(不改变值)

const str = "123" as number; // 编译通过,但运行时还是string(可能报错)

// 类型转换(改变值)

const num = Number("123"); // 运行时转为number(123)

七、结尾:类型系统,代码的"安全气囊"

TypeScript的类型系统就像开车时的安全气囊——平时感觉不到它的存在,但关键时刻能避免"翻车"(类型错误)。掌握各种类型的特点和使用场景,你就能写出更健壮、易维护的代码,面试时也能轻松应对类型相关的问题~

下次写代码时,记得让TypeScript的类型检查帮你"把好第一关"!如果这篇文章帮你理清了思路,记得点个收藏,咱们下期聊,不见不散!

相关文章

【海马S5】海马郑州S5报价
下载365App

【海马S5】海马郑州S5报价

📅 07-05 👁️ 2225
坟场导赏团 带市民了解名人历史
office365打不开doc文件

坟场导赏团 带市民了解名人历史

📅 07-13 👁️ 786
挪威:冷门传奇的始末
365bet亚洲最大网投

挪威:冷门传奇的始末

📅 07-16 👁️ 372