TypeScript 面试题
1、什么是 TypeScript?
TypeScript 是 JavaScript 的超集(加强版),它给 JavaScript 添加了可选的静态类型和基于类的面向对象编程,拓展了 JavaScript 的语法。
而且 TypeScript 不存在跟浏览器不兼容的问题,因为在编译时,它产生的都是普通的 JavaScript 代码。
2、TypeScript 和 JavaScript 的区别是什么?
TypeScript 是 JavaScript 的超集,可以被编译成 JavaScript 代码。用 JavaScript 编写的合法代码,在 TypeScript 中依然有效。TypeScript 是一种引入了静态类型和面向对象概念的编程语言。程序员可以用它来编写面向对象的服务端或客户端程序,并将它们编译成 JavaScript 代码。
TypeScript 引入了很多面向对象程序设计的特征,包括:
- Interfaces(接口)
- Classes(类)
- Enumerated types(枚举类型)
- Generics(泛型)
- Modules(模块)
主要不同点如下:
- TS 是一种静态类型语言,支持面向对象编程;而 JS 是一种动态类型的脚本语言。
- TS 支持可选参数,JS 只有默认参数,不支持显式的可选参数声明。
- TS 支持静态类型,可以在编译阶段进行类型检查;JS 不支持静态类型。
- TS 支持接口(Interface)、枚举(Enum)等高级特性,JS 原生不支持。
3、为什么要用 TypeScript?
- TS 在开发(编译)时就能给出编译错误,而 JS 的错误通常需要在运行时才能暴露。
- 作为强类型语言,你可以明确知道数据的类型,代码可读性和可维护性极强,配合 IDE 的智能提示能极大提升开发效率。
- TS 非常流行,被很多业界大佬和主流框架(如 Angular, Vue3, React)广泛使用。
4、TypeScript 和 JavaScript 哪个更好?
由于 TS 的先天优势,TS 越来越受欢迎。但是 TS 最终不可能取代 JS,因为 JS 是 TS 的编译目标和核心。
选择 TypeScript 还是 JavaScript 由项目规模和开发者决定。如果你喜欢类型安全的语言,且项目处于中大型规模,推荐使用 TS;如果是快速开发的小型脚本或原型,继续使用 JS 也是不错的选择。
5、什么是泛型?
泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而是在使用时再去指定类型的一种特性。可以把泛型理解为代表类型的参数。
// 1. 如果使用 any 的话,就失去了类型检查的意义
function createArray1(length: any, value: any): Array<any> {
let result: any = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
// 2. 最傻的写法:每种类型都得定义一种函数
function createArray2(length: number, value: string): Array<string> {
let result: Array<string> = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
// 3. 或者使用函数重载,写法有点麻烦
function createArray4(length: number, value: number): Array<number>;
function createArray4(length: number, value: string): Array<string>;
function createArray4(length: number, value: any): Array<any> {
let result: Array<any> = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
// 4. 使用泛型:有关联的地方都改成 <T>
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
// 使用的时候再指定类型
let result = createArray<string>(3, 'x');
// 也可以不指定类型,TS 会自动进行类型推导
let result2 = createArray(3, 'x');
6、TS 中的类
TypeScript 是面向对象的 JavaScript。其中的类描述了所创建的对象共同的属性和方法。
传统的 JavaScript 程序使用函数和基于原型的继承来创建可重用的组件,但这对于熟悉使用基于类面向对象方式的程序员来说有些棘手。 从 ECMAScript 2015(ES6)开始,JavaScript 程序可以使用基于类的面向对象方法。在 TypeScript 里,允许开发者使用这些特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行。
7、什么是构造函数,构造函数作用是什么?
构造函数是一种特殊的方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与 new 运算符一起使用在创建对象的语句中。
TypeScript 的构造函数用关键字 constructor 来实现。可以通过 this 关键字来访问当前类体中的属性和方法。
8、实例化是什么?
一般情况下,创建一个类后并不能直接地对属性和方法进行引用,必须对类进行实例化,即创建一个对象。TypeScript 中用 new 关键字创建对象,实例化后通过 . 来访问实例的属性和方法。
9、方法重写是什么?
子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。
重写的作用在于子类可以根据需要,定义特定于自己的行为。也就是说,子类能够根据自身需求重新实现父类的方法。
10、什么是可索引类型接口?
一般用来约束数组和对象。
// 数字索引——约束数组
// index 是随便取的名字,可以任意取名
// 只要 index 的类型是 number,那么值的类型必须是 string
interface StringArray {
[index: number]: string;
}
let arr: StringArray = ['aaa', 'bbb'];
// 字符串索引——约束对象
// 只要 index 的类型是 string,那么值的类型必须是 string
interface StringObject {
[index: string]: string;
}
let obj: StringObject = { name: 'ccc' };
11、什么是函数类型接口?
对方法传入的参数和返回值进行约束。
// 普通的接口
interface discount1 {
getNum: (price: number) => number;
}
// 函数类型接口
interface discount2 {
// 注意:
// “:” 前面的是函数的签名,用来约束函数的参数
// ":" 后面的用来约束函数的返回值
(price: number): number;
}
let cost: discount2 = function(price: number): number {
return price * 0.8;
}
// 也可以使用类型别名 (Type Alias) 约束函数
type Add = (x: number, y: number) => number;
let add: Add = (a: number, b: number) => a + b;
12、什么是类类型接口?
如果接口用于一个类的话,那么接口会表示“行为的抽象”。对类的约束,让类去实现接口,类可以实现多个接口。 接口只能约束类的公有成员(实例属性/方法),无法约束私有成员、构造函数、静态属性/方法。
// 接口可以在面向对象编程中表示为行为的抽象
interface Speakable {
name: string;
// ":" 前面的是函数签名,用来约束函数的参数
// ":" 后面的用来约束函数的返回值
speak(words: string): void;
}
interface Speakable2 {
age: number;
}
// 类可以实现多个接口
class Dog implements Speakable, Speakable2 {
name!: string;
age = 18;
speak(words: string) {
console.log(words);
}
}
let dog = new Dog();
dog.speak('汪汪汪');
13、什么是混合类型接口?
一个对象可以同时作为函数和对象使用。
interface FnType {
(getName: string): string;
}
interface MixedType extends FnType {
name: string;
age: number;
}
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
// 使用类型断言
let counter = (function (start: number) {}) as Counter;
counter.interval = 123;
counter.reset = function () {};
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
14、never 和 void 的区别?
- void:表示没有任何返回值的类型。在非严格 null 检查模式下可以被赋值为
null和undefined(严格模式下只能是undefined)。拥有void返回值类型的函数能正常执行完毕并返回。 - never:表示一个永远不存在的值的类型。拥有
never返回值类型的函数无法正常返回,它要么抛出异常,要么陷入死循环无法终止。
15、TS 的学前基础?
因为 TypeScript 是对 JavaScript 的扩展(更准确的说是 ECMAScript 的扩展),所以学习 TypeScript 需要具备 ECMAScript 语言的基础:
- 熟悉语法基础(变量、语句、函数等基础概念)
- 掌握内置对象(Array、Date 等)的使用
- 掌握面向对象基本概念(构造函数、原型、继承)
