TypeScript面试:20个问题和答案

TypeScript基于数百万JavaScript开发人员所熟悉的相同语法和语义。 使用TypeScript,可以使用最新且仍在不断发展的JS功能,包括ECMAScript 2015中可用的功能以及当前仅以句子形式存在的功能。 这些功能包括例如异步功能和装饰器。 所有这些旨在帮助开发人员创建可靠的现代应用程序。

TypeScript程序被编译为常规JavaScript代码,可以在任何浏览器或Node.js中运行。 任何支持ECMAScript 3或更高版本标准的JS引擎都可以理解此代码。



该材料(我们今天发布的翻译版)包含对二十个问题的讨论,这些问题很可能会问一个即将通过面试的人,并声称他是TypeScript程序员。

问题1(1)。 什么是TypeScript?为什么用它代替JavaScript?


在括号中,问题编号后表示其复杂性,以五分制进行评估。

TypeScript(TS)是JavaScript(JS)的超集,其主要功能包括显式静态类型分配的可能性,对类和接口的支持。 与JS相比,TS的主要优点之一是能够在各种IDE中创建这样的开发环境,该环境允许在输入代码的过程中识别常见的错误。 在大型项目中使用TypeScript可以提高程序的可靠性,同时可以将其部署在常规JS应用程序可以工作的相同环境中。

以下是有关TypeScript的一些详细信息:

  • TypeScript支持ECMAScript标准的现代版本,使用该标准编写的代码在编译时考虑到了在支持较旧版本标准的平台上执行的可能性。 这意味着TS程序员可以使用ES2015和更高标准的功能,例如模块,箭头功能,类,散布运算符,解构,并在尚不支持这些标准的现有环境中执行其工作。
  • TypeScript是JavaScript的附加组件。 用纯JavaScript编写的代码是有效的TypeScript代码。
  • TypeScript通过静态分配类型的能力扩展了JavaScript。 TS型系统相当广泛。 即,它包括接口,枚举,混合类型,泛型类型,联合类型和交集类型,访问修饰符等。 使用TypeScript还可以通过使用类型推断使事情变得容易一些。
  • 与JavaScript相比,TypeScript的使用大大改善了开发过程。 事实是IDE实时接收来自TS编译器的类型信息。
  • 当使用严格的null模式(为此使用编译器标志--strictNullChecks )时,TypeScript编译器不允许向其中不允许使用这些值的那些类型的变量分配nullundefined
  • 要使用TypeScript,您需要组织项目构建过程,其中包括在JavaScript中编译TS代码的阶段。 编译器可以将源映射嵌入到由其生成的JS文件中,或创建单独的.map文件。 这使您可以设置断点并在程序执行期间直接使用TypeScript代码检查变量的值。
  • TypeScript是在Apache 2许可下发布的Microsoft 开源项目,TypeScript开发发起者是Anders Halesberg。 他参与了Turbo Pascal,Delphi和C#的创建。

来源

问题2(1)。 告诉我们有关TypeScript中的泛型类型的信息。


通用类型(泛型)使您可以创建可与不同类型一起使用的组件或功能,而不适用于任何一种。 考虑一个例子:

 /**       */ class Queue<t> { private data = []; push = (item: T) => this.data.push(item); pop = (): T => this.data.shift(); } const queue = new Queue<number>(); queue.push(0); queue.push("1"); //  :      ,      

来源

问题3(2)。 TypeScript是否支持所有面向对象编程的原理?


是的,确实如此。 面向对象编程有四个基本原则:

  • 封装形式
  • 传承
  • 抽象化
  • 多态性

使用简单明了的TypeScript工具,您可以实现所有这些原理。

来源

问题4(2)。 如何在TypeScript中检查等于null和undefined的值?


要执行此类检查,只需使用以下构造即可:

 if (value) { } 

如果不是以下列表中的内容,则括号中的表达式为true

  • null
  • undefined
  • NaN
  • 空行
  • 0
  • false

TypeScript支持与JavaScript相同的类型转换规则。

来源

问题5(2)。 如何实现TypeScript中常量的类属性?


在TypeScript中,当声明类属性时,不能使用const关键字。 当您尝试使用此关键字时,将显示以下错误消息: A class member cannot have the 'const' keyword 。 TypeScript 2.0具有一个readonly修饰符,使您可以创建只读类属性:

 class MyClass {   readonly myReadonlyProperty = 1;   myMethod() {       console.log(this.myReadonlyProperty);   } } new MyClass().myReadonlyProperty = 5; // ,        

来源

问题6(2)。 什么是TypeScript中的.map文件?


带有.map扩展名的文件存储源地图,其中包含以TypeScript编写的代码与基于其创建的JavaScript代码的对应关系的数据。 许多调试器可以使用此文件(例如,Visual Studio和Chrome开发人员工具)。 这允许在调试期间使用TypeScript程序的源代码,而不使用其JS等效项。

来源

问题7(2)。 TypeScript中的getter和setter是什么?


TypeScript支持getter和setter,它们使您可以控制对对象成员的访问。 它们使开发人员可以控制对象的读写属性。

 class foo { private _bar:boolean = false; get bar():boolean {   return this._bar; } set bar(theBar:boolean) {   this._bar = theBar; } } var myBar = myFoo.bar;  //    myFoo.bar = true;  //    

来源

问题8(2)。 TypeScript可以用于服务器开发吗?如果可以,如何使用?


用TypeScript编写的程序不仅适用于前端开发,还适用于创建服务器应用程序。 例如,在TS上,您可以为Node.js平台编写程序。 这为程序员提供了用于类型控制的其他工具,并允许您使用语言的其他功能。 要在TS上创建服务器应用程序,您只需要设置正确的代码处理过程,就可以在其输入上接收到TypeScript文件,并且输出是适合在Node.js中执行的JavaScript文件。 为了组织这样的环境,必须首先安装TypeScript编译器:

 npm i -g typescript 

使用tsconfig.json文件设置编译器参数,该文件除其他因素外确定了编译的目的以及应放置现成的JS文件的位置。 通常,此文件与babel或webpack配置文件非常相似:

 { "compilerOptions": {   "target": "es5",   "module": "commonjs",   "declaration": true,   "outDir": "build" } } 

现在,假设编译器需要处理某些内容,则需要运行它:

 tsc 

最后,考虑到适合在Node.js环境中执行的JS文件位于build文件夹中的事实,您需要在项目的根目录中运行以下命令:

 node build/index.js 

→来源

问题9(3)。 告诉我们有关TypeScript的主要组件。


TypeScript具有三个主要组件:

  • 语言 从开发人员的角度来看,这是TypeScript最重要的部分。 “语言”是语法,关键字,所有这些都使您可以用TypeScript编写程序。
  • 编译器 TypeScript具有一个开源编译器,它是跨平台的,开放规范的,并且是用TypeScript编写的。 编译器将TypeScript代码转换为JavaScript代码。 此外,如果程序出现问题,它会显示错误消息。 它使您可以将多个TypeScript文件合并为一个输出JS文件,并可以创建代码映射。
  • 辅助工具。 TypeScript帮助器工具旨在通过在各种IDE中的使用来促进开发过程。 其中包括Visual Studio, VS Code ,Sublime,用于快速启动TS代码的各种工具等。

来源

问题10(3)。 您提供的TypeScript代码是否存在任何错误? 解释你的答案。


这是代码片段:

 class Point {   x: number;   y: number; } interface Point3d extends Point {   z: number; } let point3d: Point3d = {x: 1, y: 2, z: 3}; 

此代码没有错误。 一个类声明创建两个实体:这是用于实例化该类的数据类型,以及构造函数。 由于类创建数据类型,因此可以在可以使用接口的地方使用它们。

来源


真的很喜欢这部电影)

问题11(3)。 告诉我们有关在TypeScript中使用属性装饰器的信息。


装饰器可用于更改类的行为,将它们与任何框架一起使用时,您可以从中获得更多的好处。 例如,如果您的框架具有受访问限制的方法(例如,它们仅供管理员使用),则编写@admin方法@admin将很容易,它将禁止非管理员用户访问相应的方法。 您可以创建一个@owner装饰器,该装饰器仅允许您将对象修改为其所有者。 使用装饰器的外观如下所示:

 class CRUD {   get() { }   post() { }   @admin   delete() { }   @owner   put() { } } 

来源

问题12(3)。 TypeScript可以使用强类型函数作为参数吗?


考虑以下示例:

 class Foo {   save(callback: Function) : void {       //        var result : number = 42; //             //      -  ,        number?       callback(result);   } } var foo = new Foo(); var callback = (result: string) : void => {   alert(result); } foo.save(callback); 

是否可以在save方法中使用类型化的回调组织工作? 重写代码以演示这一点。

在TypeScript中,您可以声明一个回调类型,然后重写代码:

 type NumberCallback = (n: number) => any; class Foo {   //    save(callback: NumberCallback): void {       console.log(1)       callback(42);   } } var numCallback: NumberCallback = (result: number) : void => {   console.log("numCallback: ", result.toString()); } var foo = new Foo(); foo.save(numCallback) 

来源

问题13(3)。 如何使模块中声明的类可在模块外部访问?


在模块中声明的类在此模块中可用。 在外面,无法访问它们。

 module Vehicle {   class Car {       constructor (           public make: string,           public model: string) { }   }   var audiCar = new Car("Audi", "Q7"); } //     var fordCar = Vehicle.Car("Ford", "Figo"); 

在上面的代码中,尝试初始化fordCar变量时将发生错误。 要使在模块中声明的类可在该模块外部访问,您需要使用export关键字:

 module Vehicle {   export class Car {       constructor (           public make: string,           public model: string) { }   }   var audiCar = new Car("Audi", "Q7"); } //       var fordCar = Vehicle.Car("Ford", "Figo"); 

来源

问题14(3)。 TypeScript是否支持函数重载?


TypeScript支持函数重载,但是此机制的实现与其他面向对象的语言不同。 即,在TS中,它们仅创建一个功能和一定数量的公告。 用JavaScript编译此类代码时,只有一个特定功能可见。 该机制之所以有效,是因为可以通过将不同数量的参数传递给JS函数来调用它们。

 class Foo {   myMethod(a: string);   myMethod(a: number);   myMethod(a: number, b: string);   myMethod(a: any, b?: string) {       alert(a.toString());   } } 

来源

问题15(4)。 提供给您的代码有什么问题?


这是有问题的代码:

 /* */ interface Fetcher {   getObject(done: (data: any, elapsedTime?: number) => void): void; } 

建议仅在绝对准确地了解此步骤的后果后,才在回调中使用可选参数。 这段代码具有非常特殊的含义:可以使用1个或2个参数调用done回调。 该代码的作者可能打算告诉我们,回调可能不会注意elapsedTime参数,但是为了实现这一点,您始终可以创建一个使用较少参数的回调。

来源

问题16(4)。 如何在TypeScript中重载类构造函数?


TypeScript允许您声明方法的许多变体,但只能有一个实现,并且此实现必须具有与重载方法的所有变体兼容的签名。 要重载类构造函数,可以使用几种方法:

  • 您可以使用可选参数:

     class Box {   public x: number;   public y: number;   public height: number;   public width: number;   constructor();   constructor(obj: IBox);   constructor(obj?: any) {          this.x = obj && obj.x || 0       this.y = obj && obj.y || 0       this.height = obj && obj.height || 0       this.width = obj && obj.width || 0;   } } 
  • 您可以使用默认设置:

     class Box {   public x: number;   public y: number;   public height: number;   public width: number;   constructor(obj : IBox = {x:0,y:0, height:0, width:0}) {          this.x = obj.x;       this.y = obj.y;       this.height = obj.height;       this.width = obj.width;   } } 
  • 您可以将其他重载用作静态工厂方法:

     class Person {   static fromData(data: PersonData) {       let { first, last, birthday, gender = 'M' } = data       return new this(           `${last}, ${first}`,           calculateAge(birthday),           gender       )   }   constructor(       public fullName: string,       public age: number,       public gender: 'M' | 'F'   ) {} } interface PersonData {   first: string   last: string   birthday: string   gender?: 'M' | 'F' } let personA = new Person('Doe, John', 31, 'M') let personB = Person.fromData({   first: 'John',   last: 'Doe',   birthday: '10-09-1986' }) 
  • 您可以使用联合类型:

     class foo {   private _name: any;   constructor(name: string | number) {       this._name = name;   } } var f1 = new foo("bar"); var f2 = new foo(1); 

来源

问题17(4)。 TypeScript中的interface和type关键字之间有什么区别?


以下是使用这些关键字的示例:

 interface X {   a: number   b: string } type X = {   a: number   b: string }; 

与始终代表对象的命名类型的接口声明不同,使用type关键字允许您为任何类型的类型指定别名,包括基本类型,联合类型和交集类型。

当使用type关键字而不是interface关键字时,将失去以下可能性:

  • 可以在extendsimplements表达式中使用接口,但是不能为对象类型文字使用别名。
  • 接口可以具有多个合并的声明,并且在使用type关键字时,此功能不可用。

来源

问题18(5)。 告诉我们有关TypeScript何时使用clarify关键字的信息。


在TypeScript中,使用define关键字来声明变量,变量的来源可能是不是TypeScript文件的文件。

例如,假设我们有一个名为myLibrary的库。 它没有带有TypeScript类型声明的文件,它在全局命名空间中只有myLibrary命名空间。 如果要在TS代码中使用此库,则可以使用以下构造:

 declare var myLibrary; 

TypeScript将myLibrary变量分配给any 。 这里的问题是,尽管可以在代码中使用它,但是在开发时您将没有任何关于该库的智能提示。 在这种情况下,您可以使用另一种方法获得相同的结果。 我们正在谈论使用any类型的变量:

 var myLibrary: any; 

在这两种情况下,当使用JavaScript编译TS代码时,结果都是相同的,但是declare选项具有更好的可读性。 使用此关键字将导致创建变量的所谓外部声明(环境声明)。

问题19(5)。 什么是TypeScript中的外部变量声明,什么时候应使用它们?


变量的外部声明(环境声明)是一种机制,可使TypeScript编译器知道某些源代码存在于当前文件之外。 外部广告有助于将第三方JavaScript库集成到TS程序中。

这些声明在类型声明文件中带有扩展名.d.ts。 外部变量或模块声明如下:

 declare module Module_Name { } 

包含外部代码的文件必须使用它们包含在TS文件中,如下所示:

 /// <reference path=" Sample.d.ts"></reference> 

来源

问题20(5)。 我可以从JS库自动生成TypeScript广告素材吗?


JavaScript并不总是包含足够的信息以允许TypeScript自动推断类型。 因此,几乎不可能基于JavaScript自动创建类型声明。 但是,您可以尝试使用以下工具来执行此操作:

  • Microsoft / dts-gen是Microsoft用作创建类型声明的起点的官方工具。
  • dtsmake是一个很有前途的开发工具,可以基于JS文件自动创建类型声明。 它取决于Tern代码分析系统,某些编辑器在输入JS代码时会使用该系统来实现自动完成机制。

来源

总结


我们希望对本文中的问题进行讨论将有助于您更好地了解TypeScript,也许要注意以前没有关注的内容,并且如果您准备面试,将增加成功通过它的机会。

亲爱的读者们! 您会问面试官哪些问题需要TypeScript知识申请?


-此促销代码有什么折扣?!
-好像是7%。 我会检查你是否想要...
“是的,你检查。” 我认为折扣有点高估了!
...
-抱歉,打折我有点误会。 在所有虚拟服务器上占10%。

Source: https://habr.com/ru/post/zh-CN419993/


All Articles