文章目录
前言
准备了一些TS部分高频面试题,有需要的小伙伴可以收藏,需要的时候看看,也会持续更新。
1.TS中常见的数据类型
基本数据类型
- Number:用于表示整数和浮点数,包括 NaN 和 Infinity。
- String:用于表示文本,可以用单引号 (‘’) 或双引号 (“”) 包围。
- Boolean:表示逻辑值,可以是
true
或false
。 - Null:表示一个刻意的空值。
- Undefined:表示未定义的值,通常用于未初始化的变量。
- Symbol(ES6引入):唯一且不可变的数据类型,常用于对象的唯一属性键。
引用数据类型
- Object:用于存储键值对的集合,是最通用的数据结构类型。
- Array:用于表示有序的数据集合,可以是单一类型或多种类型的混合。
- Function:函数本身也是一种类型,可以指定参数类型和返回值类型。
特殊数据类型
- Tuple(元组):表示一个已知元素数量和类型的数组。
- Enum(枚举):用于定义一组命名的常量。
- Any:可以表示任何类型,使用时编译器不会进行类型检查。
- Void:表示没有任何返回值的函数。
- Never:表示永远不会达到的终点,常用于抛出异常或无限循环的函数返回类型。
其它数据类型
- Union Types(联合类型):允许一个值可以是几种类型之一。
- Intersection Types(交叉类型):创建一个类型,它拥有多个类型的所有属性和方法。
- Type Aliases(类型别名):为复杂类型创建一个新的名字,便于复用和理解。
- Literal Types(字面量类型):直接使用具体的值作为类型,如
const myVar: 'hello' = 'hello';
。
2.枚举和常量枚举的区别
常量枚举在TypeScript中提供了更进一步的优化,特别是在关心代码体积和执行效率的场景下,而普通枚举则提供了更多的灵活性和运行时功能。根据具体需求选择合适的枚举类型是很重要的。
// 枚举
enum Color { Red, Green, Blue }
// 常量枚举
const enum Color { Red, Green, Blue }
两者区别
编译产物:
- 普通枚举:在编译时会被转换为一个对象,其中包含枚举成员作为属性。这意味着生成的JavaScript代码中会有一个实际的对象来存储枚举值,这可能会增加代码体积。
- 常量枚举:编译器会直接将枚举成员的使用替换为对应的值,而不会生成额外的对象。这样可以减小输出的JavaScript代码大小,提高运行时效率。
值的存储:
- 普通枚举:枚举值存储在枚举类型实例上,可以在运行时通过枚举实例访问。
- 常量枚举:枚举值直接内联到使用它们的地方,不生成实例,因此在运行时无法直接访问枚举类型。
可计算性:
- 普通枚举:允许更复杂的结构,如包含计算成员或基于其他枚举值的表达式。
- 常量枚举:只允许字面量值或其它常量枚举成员,不允许计算成员,因为它们的值在编译时就需要确定。
可读性和错误预防:
- 两者都提供了更清晰的代码可读性和错误预防机制,但常量枚举由于其值直接内联,可能会进一步减少类型错误,因为任何对枚举值的引用都是静态的且直接硬编码的。
使用场景:
- 普通枚举:适合需要在运行时能够访问枚举类型及其成员,或者枚举值可能需要动态计算的场景。
- 常量枚举:适用于那些枚举值不需要在运行时访问,且希望最小化代码体积和提升性能的场景,例如在大量使用枚举值作为字符串或数字常量的场合。
3.Exclude和Qmit
Exclude
和Omit
是两种用于类型操作的实用类型,它们可以帮助开发者更灵活地处理和创建复杂类型。
Exclude
Exclude< T, U > 作用:取T、U交集的补集
Exclude<T, U> 的主要作用是从 T 类型中排除可以赋值给 U 的类型,创建出一个新的子类型。
type T = 'a' | 'b' | 'c';
type U = 'a' | 'b';
type Result = Exclude<T, U>; // 结果是 'c'
Omit
Omit<T, K> 的主要功能在于,从一个已有的对象类型 T 中排除指定的属性 K,进而创建一个新的对象类型。
type T = {
a: number;
b: string;
c: boolean;
};
type K = 'a' | 'b';
type Result = Omit<T, K>; // 结果是 { c: boolean }
区别
- 目的不同:
Exclude
主要用于从联合类型中排除特定类型,而Omit
专门用于从对象类型中排除指定的属性。 - 应用场景:当你需要从一组可能的值中排除某些类型时,使用
Exclude
;当你需要创建一个对象类型的新版本,但不包含某些特定属性时,使用Omit
。 - 类型操作的层次:
Exclude
操作在类型层级,而Omit
操作在对象结构层级。
4.extends和implements
extends
和 implements
是两个关键字,用于实现面向对象编程中的继承和接口实现功能。它们分别用于类与类之间、类与接口之间的关系定义,但侧重点不同。
extends
关键字用于类继承,它允许一个类(子类)继承另一个类(父类)的属性和方法。这意味着子类可以复用父类的代码,同时可以添加自己的属性和方法,或者重写父类的方法。这有助于实现代码的复用和组织。implements
关键字用于实现接口。接口定义了一组必须实现的属性和/或方法,任何使用implements
关键字声明的类都必须提供接口中定义的所有成员的实现。这有助于确保类型的一致性和代码的规范性。
区别
extends
用于类的继承,支持单继承模型,即一个类只能直接继承自一个父类,但可以通过多级继承间接实现多重继承的效果。implements
用于类对接口的实现,一个类可以实现多个接口,以确保遵循特定的契约或定义的行为规范。
5.type 和 interface
type
和 interface
都用于定义类型,都可以描述一个对象或者函数
type
- 别名(Alias) :
type
主要用于定义类型别名,它可以用来给已存在的类型起一个新的名字,使得类型表达更加清晰或简化复杂的类型定义。类型别名不仅可以用于原始类型、联合类型、元组等,还可以用于引用其他类型别名或接口。 - 联合类型与交叉类型:
type
在定义联合类型(如type NewType = TypeA | TypeB
)和交叉类型(如type MergedType = TypeA & TypeB
)时非常方便。 - 不支持继承:与接口不同,类型别名不能被继承,也不能继承其他类型别名或接口。它更像是给类型起一个易于理解的名字。
- 声明合并:
type
不参与声明合并。这意味着,如果在不同的文件中使用相同的type
名称,它们不会被合并成一个类型定义。
interface
- 接口(Interface) :
interface
用于定义对象的形状(shape),描述了对象应该具有哪些属性和方法。它可以用来定义类的公共部分,支持实现多接口。 - 类的定义与实现:接口可以直接用于类的定义(通过
implements
关键字)和类的继承(通过extends
关键字,虽然在接口间更多体现为“继承”接口成员而非真正意义上的继承)。 - 扩展与合并:接口支持扩展其他接口(如
interface B extends A {}
),这使得接口可以逐渐累加定义,形成层次化的类型定义。同时,即使在不同文件中定义了同名接口,TypeScript 也会自动将它们合并为一个接口。 - 索引签名与元组类型:虽然
type
也可以定义复杂的类型结构,但接口在定义索引签名(如映射类型)和描述数组或元组的结构方面更为直观。
区别
类型别名可以为任何类型引入名称,例如基本类型,联合类型等。
- 类型别名不支持继承
- 类型别名不会创建一个类型的名字
- 类型别名无法被实现implements,而接口可以被派生类实现
- 类型别名重名会抛出错误,接口重名是会产生合并
当你需要描述对象的形状或实现面向对象设计时(如类的定义、接口的继承和实现),通常使用 interface
。 当你需要为现有类型提供一个更易读的别名,或者定义联合类型、交叉类型等复合类型时,应使用 type
。