跳到主内容

TypeScript面试题

本文整理了前端常见的 TypeScript 面试题,包括什么是泛型,unknown 和 any 的区别,interface 和 type 的区别,什么是三斜线指令,什么是装饰器等等

什么是泛型

官方的解释如下

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

简单来说泛型就是解决类,接口,方法的复用性(传入什么类型就返回什么类型),以及对不特定数据类型的支持

unknown 和 any 的区别

TypeScript 3.0 引入了一个顶级的 unknown 类型。

  1. unknown 是类型安全的。

  2. 同 any 一样,任何值都可以赋给 unknown,但是 unknown 不可以赋值给其它类型,只能赋值给 any 和 unknown。

let vAny: any = 10; // 任何值都可以赋值给any
let vUnknown: unknown = 10; // 任何值都可以赋值给unknown

let s1: string = vAny; // 正确
let s2: string = vUnknown; // 报错

vAny.method(); // 正确
vUnknown.method(); // 报错
  1. unknown 没有被断言或细化到一个确切类型之前,是不允许在其上进行任何操作的。
// 错误的写法
function foo(callback: unknown) {
callback(); // 编译报错 Object is of type 'unknown'.
}

// 正确的写法
function foo(callback: unknown) {
if (typeof callback === "function") {
callback();
}
}

什么时候应该使用关键字 unknown

unknown,如果你不知道预先期望哪种类型,但想稍后分配它,则应该使用该 any 关键字,并且该关键字将不起作用。

interface(接口)和 type(类型别名)的区别

interface 和 type 很多情况下功能都类似,都是用来声明变量的类型,首先用 interface 实现,若 interface 无法实现再用 type 实现。他们的区别如下:

  1. 都可以声明对象、函数,但是 type 还可以声明基础类型、联合类型、元祖。

  2. interface 多次声明可以合并,type 不能重复声明

  3. type 可以使用 typeof 获取变量的类型

let div = document.createElement("div");
type B = typeof div;

TS 的模块是什么?

TypeScript 中的模块是相关变量、函数、类和接口的集合。你可以将模块视为包含执行任务所需的一切的容器。可以导入模块以轻松地在项目之间共享代码。

module moduleName {
class xyz {
export sum(x, y){
return x+y;
}
}

什么是三斜线指令?

三斜线指令是单行注释,包含用作编译器指令的 XML 标记。每个指令都表示在编译过程中要加载的内容。三斜杠指令仅在其文件的顶部工作,并且将被视为文件中其他任何地方的普通注释。

/// <reference path="..." /> 是最常见的指令,定义文件之间的依赖关系。

/// <reference types="..." /> 类似于path但定义了包的依赖项。

/// <reference lib="..." /> 允许您显式包含内置lib文件。

Omit 类型有什么作用

Omit 以一个类型为基础支持剔除某些属性,然后返回一个新类型。

语法如下

Omit<Type, Keys>

使用示例

interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
type TodoPreview = Omit<Todo, "description">;

TypeScript 中如何实现函数重载

要在 TypeScript 中重载函数,只需创建两个名称相同但参数/返回类型不同的函数。两个函数必须接受相同数量的参数。这是 TypeScript 中多态性的重要组成部分。

例如,你可以创建一个 add 函数,如果它们是数字,则将两个参数相加,如果它们是字符串,则将它们连接起来。

function add(a:string, b:string):string;
function add(a:number, b:number): number;
function add(a: any, b:any): any {
return a + b;
}
add("Hello ", "1024nav"); // returns "Hello 1024nav"
add(10, 20); // returns 30

什么是装饰器

在一些场景下我们需要额外的特性来支持标注或修改类及其成员。 装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。 Javascript 里的装饰器目前处在 建议征集的第二阶段,但在 TypeScript 里已做为一项实验性特性予以支持。

装饰器定义

function sealed(target) {
// 给目标值添加一些特性
}

下面举例一个方法装饰器

定义一个 enumerable

function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}

使用装饰器,给 greet 方法限制不可枚举

class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}

@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}