📅  最后修改于: 2021-01-11 13:06:38             🧑  作者: Mango
下面列出了最常见的TypeScript面试问题和答案。
TypeScript是由Microsoft开发和维护的一种免费的开源编程语言。它是JavaScript的强类型超集,可编译为纯JavaScript。它是用于应用程序级JavaScript开发的语言。对于熟悉C#,Java和所有强类型语言的开发人员而言,TypeScript非常易于学习和使用。
TypeScript可以在任何浏览器,任何主机和任何操作系统上执行。 TypeScript不能直接在浏览器上运行。它需要编译器才能在JavaScript文件中进行编译和生成。 TypeScript是JavaScript的ES6版本,具有一些附加功能。
TypeScript在以下方面不同于JavaScript:
SN | JavaScript | TypeScript |
---|---|---|
1 | It was developed by Netscape in 1995. | It was developed by Anders Hejlsberg in 2012. |
2 | JavaScript source file is in “.js” extension. | TypeScript source file is in “.ts” extension. |
3 | JavaScript doesn’t support ES6. | TypeScript supports ES6. |
4 | It doesn’t support strongly typed or static typing. | It supports strongly typed or static typing feature. |
5 | It is just a scripting language. | It supports object-oriented programming concept like classes, interfaces, inheritance, generics, etc. |
6 | JavaScript has no optional parameter feature. | TypeScript has optional parameter feature. |
7 | It is interpreted language that’s why it highlighted the errors at runtime. | It compiles the code and highlighted errors during the development time. |
8 | JavaScript doesn’t support modules. | TypeScript gives support for modules. |
9 | In this, number, string are the objects. | In this, number, string are the interface. |
10 | JavaScript doesn’t support generics. | TypeScript supports generics. |
要了解更多信息,请单击此处。
我们需要TypeScript:
要了解更多信息,请单击此处。
TypeScript具有以下优点。
TypeScript具有以下缺点:
TypeScript主要包含三个组件。这些是-
语言
该语言包含新语法,关键字,类型注释之类的元素,并允许我们编写TypeScript。
编译器
TypeScript编译器是开放源代码,跨平台的,并使用TypeScript编写。它将用TypeScript编写的代码转换成与其JavaScript代码等效的代码。它执行我们的TypeScript代码到JavaScript代码的解析和类型检查。它还可以帮助将不同的文件连接到单个输出文件并生成源映射。
语言服务
语言服务提供的信息可帮助编辑人员和其他工具提供更好的辅助功能,例如自动重构和IntelliSense。
要了解更多信息,请单击此处。
打字稿由Anders Hejlsberg开发,他也是C#语言开发团队的核心成员之一。打字稿于2012年10月1日首次发布,标为版本0.8 。它由Microsoft根据Apache 2许可开发和维护。它是为开发大型应用程序而设计的。
打字稿的当前稳定版本是3.2,其发布于9月30日,2018年打字稿编译为运行在任何浏览器支持ECMAScript的2015年框架简单的JavaScript代码。它支持最新和不断发展的JavaScript功能。
可以通过npm(Node.js程序包管理器)在Node的帮助下安装和管理TypeScript。要安装TypeScript,请首先确保正确安装了npm ,然后运行以下命令在系统上全局安装TypeScript。
$ npm install -g typescript
它安装了命令行代码“ tsc” ,该代码将进一步用于编译我们的Typescript代码。确保我们检查系统上安装的Typescript版本。
安装TypeScript涉及以下步骤:
要了解安装过程,请单击此处。
内置数据类型在Typescript中也称为原始数据类型。这些在下面给出。
数字类型:用于表示数字类型的值。 TypeScript中的所有数字都存储为浮点值。
语法: let标识符:number = value;
字符串类型:它表示存储为Unicode UTF-16代码的一系列字符。通过将字符串字面量包含在单引号或双引号中,我们将它们包含在脚本中。
语法: let标识符: 字符串 =“”;
布尔类型:用于表示逻辑值。当我们使用布尔类型时,我们只能得到true或false的输出。布尔值是一个真值,它指定条件是否为真。
语法:let标识符: bool =布尔值;
空类型:空表示变量,其值未定义。无法直接引用空类型值本身。空类型没有用,因为我们只能为其分配空值。
语法:let num: number = null;
未定义类型:这是未定义字面量的类型。 Undefined类型表示所有未初始化的变量。它没有用,因为我们只能为其分配一个未定义的值。内置类型是所有类型的子类型。
语法: let num:number = undefined;
无效类型:无效是不返回任何类型的值的函数的返回类型。在没有可用数据类型的地方使用它。
语法: let不可用:void = undefined;
要详细了解TypeScript数据类型,请单击此处。
变量是存储位置,用于存储程序要引用和使用的值/信息。它充当程序中价值的容器。可以使用var关键字声明。使用前应声明。在Typescript中声明变量时,应遵循某些规则-
我们可以用以下四种方式之一声明变量:
要了解更多详细信息,请单击此处。 https://www.javatpoint.com/typescript-variables
这是将Typescript文件编译为JavaScript时遵循的命令。
$ tsc
例如,编译“ Helloworld.ts”。
$ tsc helloworld.ts
结果将是helloworld.js。
对的,这是可能的。为此,我们需要添加–outFILE [OutputJSFileName]编译选项。
$ tsc --outFile comman.js file1.ts file2.ts file3.ts
上面的命令将编译所有三个“ .ts”文件,并将结果存储到单个“ comman.js”文件中。在这种情况下,当我们不像下面的命令那样提供输出文件名时。
$ tsc --outFile file1.ts file2.ts file3.ts
然后,将编译file2.ts和file3.ts ,并将输出放置在file1.ts中。因此,现在我们的file1.ts包含JavaScript代码。
是的,可以通过.ts文件中的实时更改自动编译“ .ts”。这可以通过使用–watch编译器选项来实现
tsc --watch file1.ts
上面的命令首先在file1.js中编译file1.ts ,并观察文件更改。如果检测到任何更改,它将再次编译文件。在这里,我们需要确保在使用–watch选项运行时一定不要关闭命令提示符。
接口是在我们的应用程序中充当合同的结构。它定义了要遵循的类的语法,这意味着实现接口的类必须实现其所有成员。它不能被实例化,但是可以由实现它的类对象引用。 TypeScript编译器使用接口进行类型检查(也称为“鸭子类型”或“结构子类型”),以检查对象是否具有特定的结构。
句法:
interface interface_name {
// variables' declaration
// methods' declaration
}
该接口仅声明方法和字段。它不能用于构建任何东西。接口无需转换为JavaScript即可执行。它们对运行时JavaScript的影响为零。因此,它们的唯一目的是在开发阶段提供帮助。
我们知道,TypeScript是一种面向对象的JavaScript语言,并支持OOP编程功能,例如类,接口等。与Java一样,类是用于创建可重用组件的基本实体。它是一组具有共同属性的对象。类是用于创建对象的模板或蓝图。它是一个逻辑实体。 “ class”关键字用于在Typescript中声明一个类。
例:
class Student {
studCode: number;
studName: string;
constructor(code: number, name: string) {
this.studName = name;
this.studCode = code;
}
getGrade() : string {
return "A+" ;
}
}
一类的特点是-
否。当前,本机JavaScript不支持模块。为了在Javascript中创建和使用模块,我们需要一个像CommonJS这样的外部对象。
TypeScript支持以下面向对象的术语。
super()函数用于从子类中调用父类或基类构造函数。
继承是一种从另一个类获取一个类的属性和行为的机制。它是OOP语言的重要方面,并且具有从现有类创建新类的能力。其成员被继承的类称为基类,而继承这些成员的类称为派生类。
可以通过使用extend关键字来实现继承。通过以下示例我们可以理解它。
class Shape {
Area:number
constructor(area:number) {
this.Area = area
}
}
class Circle extends Shape {
display():void {
console.log("Area of the circle: "+this.Area)
}
}
var obj = new Circle(320);
obj.display() //Output: Area of the circle: 320
要了解更多信息,请单击此处。
模块是创建一组相关变量,函数,类和接口等的强大方法。它可以在自己的范围内执行,而不是在全局范围内执行。换句话说,在模块中声明的变量,函数,类和接口不能直接在模块外部访问。
创建一个模块
可以使用export关键字创建一个模块,并且可以使用import关键字在其他模块中使用该模块。
module module_name{
class xyz{
export sum(x, y){
return x+y;
}
}
}
要了解更多信息,请单击此处。
内部和外部模块之间的区别如下:
SN | Internal Module | External Module |
---|---|---|
1 | Internal modules were used to logically group the classes, interfaces, functions, variables into a single unit and can be exported in another module. | External modules are useful in hiding the internal statements of the module definitions and show only the methods and parameters associated with the declared variable. |
2 | Internal modules were in the earlier version of Typescript. But they are still supported by using namespace in the latest version of TypeScript. | External modules are simply known as a module in the latest version of TypeScript. |
3 | Internal modules are local or exported members of other modules (including the global module and external modules). | External modules are separately loaded bodies of code referenced using external module names. |
4 | Internal modules are declared using ModuleDeclarations that specify their name and body. | An external module is written as a separate source file that contains at least one import or export declaration. |
5 | Example:
module Sum { export function add(a, b) { console.log("Sum: " +(a+b)); } } |
Example:
export class Addition{ constructor(private x?: number, private y?: number){ } Sum(){ console.log("SUM: " +(this.x + this.y)); } } |
要了解更多详细信息,请单击此处。
命名空间是一种用于功能逻辑分组的方法。命名空间用于在内部维护打字稿的旧代码。它封装了共享某些关系的要素和对象。命名空间也称为内部模块。命名空间还可以包括接口,类,函数和变量,以支持一组相关功能。
注意:可以在多个文件中定义一个名称空间,并允许将每个文件都保留在一个地方,因为它们都是定义的。它使代码更易于维护。
用于创建名称空间的Synatax
namespace {
export interface I1 { }
export class c1{ }
}
要了解更多信息,请单击此处。
装饰器是一种特殊的声明,可以应用于类,方法,访问器,属性或参数。装饰器只是带有@expression符号前缀的函数,其中expression必须求值为一个函数,该函数将在运行时使用有关修饰声明的信息进行调用。
TypeScript装饰器的目的是以声明的方式将注释和元数据添加到现有代码中。装饰器是为ES7建议的实验功能。包括Angular 2在内的某些JavaScript框架已在使用它。装饰器在将来的版本中可能会更改。
要为装饰器启用实验性支持,我们必须在命令行或tsconfig.json中启用experimentalDecorators编译器选项:
命令行
$tsc --target ES5 --experimentalDecorators
tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
要了解更多信息,请单击此处。
在Javascript中,Mixins是一种通过可重用组件构建类的方法,即通过组合称为mixins的更简单的局部类来构建它们。
这个想法很简单,函数B代替了类A扩展类B以获取其功能,而是采用类A并返回具有此附加功能的新类。函数B是一个mixin。
“公共”是TypeScript类中属性/方法的默认可见性。
与JavaScript不同,如果我们尝试调用一个函数而不提供其函数签名中声明的确切数量和类型的参数,则TypeScript编译器将引发错误。为了克服这个问题,我们可以通过使用问号('?')来使用可选参数。这意味着可以或不可以接收值的参数可以附加“?”将其标记为可选。
function Demo(arg1: number, arg2? :number) {
}So, arg1 is always required, and arg2 is an optional parameter.
因此,始终需要arg1 ,而arg2是可选参数。
注意:可选参数必须遵循必需的参数。如果要使arg1可选,而不是arg2,则需要更改顺序,并且必须将arg1放在arg2之后。
function Demo(arg2: number, arg1? :number) {
}
要了解更多信息,请单击此处。
是的,TypeScript支持函数重载。但是实现很奇怪。当我们在TypeScript中执行函数重载时,我们只能实现一个具有多个签名的函数。
//Function with string type parameter
function add(a:string, b:string): string;
//Function with number type parameter
function add(a:number, b:number): number;
//Function Definition
function add(a: any, b:any): any {
return a + b;
}
在上面的示例中,前两行是函数重载声明。它有两个重载。第一个签名的参数类型为字符串,而第二个签名的参数类型为数字。第三个函数包含实际的实现,并且具有类型为any的参数。任何数据类型都可以采用任何类型的数据。然后,实现会检查所提供参数的类型,并根据供应商参数类型执行另一段代码。
对的,这是可能的。要调试任何TypeScript文件,我们需要.js源映射文件。因此,请使用–sourcemap标志编译.ts文件以生成源映射文件。
$ tsc -sourcemap file1.ts
这将创建file1.js和file1.js.map。 file1.js的最后一行将是源映射文件的引用。
//# sourceMappingURL=file1.js.map
TypeScript Definition Manager(TSD)是一个程序包管理器,用于直接从社区驱动的DefinitelyTyped存储库中搜索和安装TypeScript定义文件。
假设我们要在.ts文件中使用一些jQuery代码。
$(document).ready(function() { //Your jQuery code });
现在,当我们尝试使用tsc对其进行编译时,将出现编译时错误:找不到名称“ $”。因此,我们需要通知TypeScript编译器“ $”属于jQuery。为此,TSD发挥了作用。我们可以下载jQuery Type Definition文件并将其包含在我们的.ts文件中。以下是执行此操作的步骤:
首先,安装TSD。
$ npm install tsd -g
在TypeScript目录中,通过运行以下命令创建一个新的TypeScript项目:
$ tsd init
然后安装jQuery的定义文件。
tsd query jquery --action install
上面的命令将下载并创建一个新目录,其中包含以“ .d.ts”结尾的jQuery定义文件。现在,通过更新TypeScript文件以指向jQuery定义来包含定义文件。
///
$(document).ready(function() { //To Do
});
现在,再次编译。这次生成的js文件没有任何错误。因此,TSD的需求有助于我们获取所需框架的类型定义文件。
我们知道所有JavaScript库/框架都没有TypeScript声明文件,但是我们希望在我们的TypeScript文件中使用它们而不会出现任何编译错误。为此,我们使用clarify关键字。 define关键字用于环境声明和我们要定义可能存在于其他位置的变量的方法。
例如,假设我们有一个名为myLibrary的库,它没有TypeScript声明文件,并且在全局名称空间中有一个名为myLibrary的名称空间。如果要在TypeScript代码中使用该库,可以使用以下代码:
declare var myLibrary;
TypeScript运行时会将myLibrary变量分配为任何类型。这是我们在设计时无法获得Intellisense的问题,但是我们将能够在代码中使用该库。
我们可以使用tsc编译器从任何.ts文件生成TypeScript定义文件。它将生成一个TypeScript定义,该定义使我们的TypeScript文件可重复使用。
tsc --declaration file1.ts
tsconfig.json文件是JSON格式的文件。在tsconfig.json文件中,我们可以指定各种选项来告诉编译器如何编译当前项目。目录中存在tsconfig.json文件,表明该目录是TypeScript项目的根目录。下面是一个示例tsconfig.json文件。
{
"compilerOptions": {
"declaration": true,
"emitDecoratorMetadata": false,
"experimentalDecorators": false,
"module": "none",
"moduleResolution": "node"
"removeComments": true,
"sourceMap": true
},
"files": [
"main.ts",
"othermodule.ts"
]
}
要了解更多信息,请单击此处。
TypeScript Generics是一种工具,提供了一种创建可重用组件的方法。它能够创建可以使用多种数据类型而不是单一数据类型的组件。泛型在不影响性能或生产率的情况下提供了类型安全性。泛型允许我们创建泛型类,泛型函数,泛型方法和泛型接口。
在泛型中,类型参数写在左括号(<)和右括号(>)之间,这使它成为强类型集合。泛型使用一种特殊的类型变量
function identity(arg: T): T {
return arg;
}
let output1 = identity("myString");
let output2 = identity( 100 );
console.log(output1);
console.log(output2);
要了解更多信息,请单击此处。
是的,TypeScript支持所有面向对象的原理。面向对象编程有四个主要原则:
通过使用杂项检查,我们可以检查null和undefined:
if (x == null) {
}
如果我们使用严格检查,则对于设置为null的值将始终为true,而对于未定义的变量则不会为true。
例
var a: number;
var b: number = null;
function check(x, name) {
if (x == null) {
console.log(name + ' == null');
}
if (x === null) {
console.log(name + ' === null');
}
if (typeof x === 'undefined') {
console.log(name + ' is undefined');
}
}
check(a, 'a');
check(b, 'b');
输出量
"a == null"
"a is undefined"
"b == null"
"b === null"
是的,我们可以在后端使用TypeScript。我们可以通过以下示例了解它。在这里,我们选择Node.js,并具有一些附加的类型安全性以及该语言带来的其他抽象。
npm i -g typescript
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"outDir": "build"
}
}
tsc
node build/index.js
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
SN | interface | type |
---|---|---|
1 | An interface declaration always introduces a named object type. | A type alias declaration can introduce a name for any kind of type, including primitive, union, and intersection types. |
2 | An interface can be named in an extends or implements clause. | Type alias for an object type literal cannot be named in an extends or implements clause. |
3 | Interfaces create a new name that is used everywhere. | Type aliases don’t create a new name. |
4 | An interface can have multiple merged declarations. | Type alias for an object type literal cannot have multiple merged declarations. |
环境声明告诉编译器其他地方存在的实际源代码。如果这些源代码在运行时不存在,而我们尝试使用它们,则它将中断而不会发出警告。
环境声明文件类似于docs文件。如果源更改,则还需要保持文档更新。如果环境声明文件未更新,那么我们将得到编译器错误。
Ambient声明使我们能够安全,轻松地使用现有流行的JavaScript库,例如jquery,angularjs,nodejs等。
类型断言的工作方式类似于其他语言的类型转换,但是它不像其他语言可以执行C#和Java一样执行类型检查或数据重组。类型转换附带运行时支持,而类型断言对运行时没有影响。但是,类型断言仅由编译器使用,并向编译器提供有关我们希望如何分析代码的提示。
例
let empCode: any = 111;
let employeeCode = code;
console.log(typeof(employeeCode)); //Output: number
要了解更多信息,请单击此处。
as是TypeScript中类型断言的附加语法。引入as语法的原因是原始语法(
例
let empCode: any = 111;
let employeeCode = code as number;
当将TypeScript与JSX一起使用时,仅允许使用as样式的断言。
JSX没有其他扩展名的Javascript。 Facebook提出了这个新扩展,以便他们可以与JavaScript中类似XML的HTML实现区别开来。
JSX是一种可嵌入的类似XML的语法。它打算转换为有效的JavaScript。 JSX在React框架中开始流行。 TypeScript支持嵌入,类型检查以及直接将JSX编译到JavaScript中。
要使用JSX,我们必须做两件事。
rest参数用于将零个或多个值传递给函数。通过在参数前面加上三个点字符('…')来声明它。它允许函数具有可变数量的参数,而无需使用arguments对象。如果参数数量不确定,这将非常有用。
其余参数遵循的规则:
function sum(a: number, ...b: number[]): number {
let result = a;
for (var i = 0; i < b.length; i++) {
result += b[i];
}
console.log(result);
}
let result1 = sum(3, 5);
let result2 = sum(3, 5, 7, 9);
要了解更多信息,请单击此处。
枚举或枚举是TypeScipt数据类型,它允许我们定义一组命名常量。使用枚举可以更轻松地记录意图或创建一组不同的案例。它是相关值的集合,可以是数字值或字符串值。
例
enum Gender {
Male,
Female
Other
}
console.log(Gender.Female); // Output: 1
//We can also access an enum value by it's number value.
console.log(Gender[1]); // Output: Female
Non-Relative | Relative |
---|---|
A non-relative import can be resolved relative to baseUrl, or through path mapping. In other words, we use non-relative paths when importing any of our external dependencies. Example: import * as $ from "jquery"; import { Component } from "@angular/core"; |
Relative imports can be used for our own modules that are guaranteed to maintain their relative location at runtime. A relative import is starts with /, ./ or ../. Example: import Entry from "./components/Entry"; import {DefaultHeaders} from "../constants/http"; |
匿名函数是在没有任何命名标识符的情况下声明的函数。这些函数在运行时动态声明。就像标准函数一样,匿名函数可以接受输入和返回输出。初始创建后,匿名函数通常不可访问。
例
let myAdd = function(x: number, y: number): number {
return x + y;
};
console.log(myAdd())
声明合并是编译器遵循的合并两个或更多单独声明的过程。将具有相同名称的声明声明为单个定义。此合并的定义具有两个原始声明的功能。
声明合并的最简单(也许是最常见)的类型是接口合并。在最基本的级别上,合并会将两个声明的成员机械地连接到具有相同名称的单个接口中。
例
interface Cloner {
clone(animal: Animal): Animal;
}
interface Cloner {
clone(animal: Sheep): Sheep;
}
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}
这三个接口将合并以创建单个声明,如下所示:
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Sheep): Sheep;
clone(animal: Animal): Animal;
}
注意:TypeScript中不允许所有合并。当前,类不能与其他类或变量合并。
如果子类(子类)具有与父类中声明的方法相同的方法,则称为方法重写。换句话说,在派生类或子类中重新定义基类方法。
方法覆盖规则
例
class NewPrinter extends Printer {
doPrint(): any {
super.doPrint();
console.log("Called Child class.");
}
doInkJetPrint(): any {
console.log("Called doInkJetPrint().");
}
}
let printer: new () => NewPrinter;
printer.doPrint();
printer.doInkJetPrint();
ES6版本的TypeScript提供了用于定义匿名函数(即函数表达式)的简写语法。这些箭头函数也称为Lambda函数。 Lambda函数是没有名称的函数。箭头函数省略了函数关键字。
例
let sum = (a: number, b: number): number => {
return a + b;
}
console.log(sum(20, 30)); //returns 50
在上面,?=>?是lambda运算符,(a + b)是函数的主体,(a:number,b:number)是内联参数。
要了解更多信息,请单击此处。