我要涨知识 —— TypeScript 常见面试题(一)
1、ts 中的 any 和 unknown 有什么区别?
unknown 和 any 的主要区别是 unknown 类型会更加严格:在对 unknown 类型的值执行大多数操作之前,我们必须进行某种形式的检查。而在对 any 类型的值执行操作之前,我们不必进行任何检查。
举例说明:
let foo: any = 123; console.log(foo.msg); // 符合TS的语法 let a_value1: unknown = foo; // OK let a_value2: any = foo; // OK let a_value3: string = foo; // OK let bar: unknown = 222; // OK console.log(bar.msg); // Error let k_value1: unknown = bar; // OK let K_value2: any = bar; // OK let K_value3: string = bar; // Error
因为bar是一个未知类型(任何类型的数据都可以赋给 unknown 类型),所以不能确定是否有msg属性。不能通过TS语法检测;而 unknown 类型的值也不能将值赋给 any 和 unknown 之外的类型变量
总结:
any 和 unknown 都是顶级类型,但是 unknown 更加严格,不像 any 那样不做类型检查,反而 unknown 因为未知性质,不允许访问属性,不允许赋值给其他有明确类型的变量。
2、说说你对 typescript 的理解?与 javascript 的区别?
2.1、TS是什么?
TypeScript 是 JavaScript 的类型的超集,支持ES6语法,支持面向对象编程的概念,如类、接口、继承、泛型等
超集,不得不说另外一个概念,子集,怎么理解这两个呢,举个例子,如果一个集合A里面的的所有元素集合B里面都存在,那么我们可以理解集合B是集合A的超集,集合A为集合B的子集
其是一种静态类型检查的语言,提供了类型注解,在代码编译阶段就可以检查出数据类型的错误
同时扩展了JavaScript 的语法,所以任何现有的JavaScript 程序可以不加改变的在 TypeScript 下工作
为了保证兼容性,typescript在编译阶段需要编译器编译成纯Javascript来运行,是为大型应用之开发而设计的语言,如下:
tsx文件如下:
const hello : string = "Hello World!"
console.log(hello)
复制代码
编译文件后:
const hello = "Hello World!"
console.log(hello)
复制代码
2.2、特性
typescript的特性主要有如下:
- 类型批注和编译时类型检查 :在编译时批注变量类型
- 类型推断:ts中没有批注变量类型会自动推断变量的类型
- 类型擦除:在编译过程中批注的内容和接口会在运行时利用工具擦除
- 接口:ts中用接口来定义对象类型
- 枚举:用于取值被限定在一定范围内的场景
- Mixin:可以接受任意类型的值
- 泛型编程:写代码时使用一些以后才指定的类型
- 名字空间:名字只在该区域内有效,其他区域可重复使用该名字而不冲突
- 元组:元组合并了不同类型的对象,相当于一个可以装不同类型数据的数组
2.3、类型批注
通过类型批注提供在编译时启动类型检查的静态类型,这是可选的,而且可以忽略而使用JavaScript常规的动态类型
function Add(left: number, right: number): number { return left + right; }
对于基本类型的批注是number、bool和string,而弱或动态类型的结构则是any类型
2.4、类型推断
当类型没有给出时,TypeScript编译器利用类型推断来推断类型,如下:
let str = 'string'
变量str被推断为字符串类型,这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时
如果由于缺乏声明而不能推断出类型,那么它的类型被视作默认的动态any类型
2.5、接口
接口简单来说就是用来描述对象的类型 数据的类型有number、null、string等数据格式,对象的类型就是用接口来描述的
interface Person { name: string; age: number; } let tom: Person = { name: 'Tom', age: 25 };
2.6、TS 与 JS 的区别
- TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法
- TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译
- TypeScript 文件的后缀名 .ts (.ts,.tsx,.dts),JavaScript 文件是 .js
- 在编写 TypeScript 的文件的时候就会自动编译成 js 文件
更多的区别如下图所示:
3、为什么推荐使用 TypeScript ?
TypeScript是微软公司开发和维护的一种面向对象的编程语言。它是JavaScript的超集,包含其所有元素。
强类型和弱类型、静态类型和动态类型是两组不同的概念。
类型强弱是针对类型转换是否显示来区分,静态和动态类型是针对类型检查的时机来区分。
TS对JS的改进主要是静态类型检查,静态类型检查有何意义?标准答案是“静态类型更有利于构建大型应用”。
推荐使用TypeScript的原因有:
- TypeScript简化了JavaScript代码,使其更易于阅读和调试。
- TypeScript是开源的。
- TypeScript为JavaScript ide和实践(如静态检查)提供了高效的开发工具。
- TypeScript使代码更易于阅读和理解。
- 使用TypeScript,我们可以大大改进普通的JavaScript。
- TypeScript为我们提供了ES6(ECMAScript 6)的所有优点,以及更高的生产率。
- TypeScript通过对代码进行类型检查,可以帮助我们避免在编写JavaScript时经常遇到的令人痛苦的错误。
- 强大的类型系统,包括泛型。
- TypeScript只不过是带有一些附加功能的JavaScript。
- TypeScript代码可以按照ES5和ES6标准编译,以支持最新的浏览器。
- 与ECMAScript对齐以实现兼容性。
- 以JavaScript开始和结束。
- 支持静态类型。
- TypeScript将节省开发人员的时间。
- TypeScript是ES3、ES5和ES6的超集。
4、TypeScript 的内置数据类型有哪些?
数字类型:用于表示数字类型的值。TypeScript 中的所有数字都存储为浮点值。
let identifier: number = value;
布尔类型:一个逻辑二进制开关,包含true或false
let identifier: string = " ";
Null 类型: Null 表示值未定义的变量。
let identifier: bool = Boolean value;
未定义类型:一个未定义的字面量,它是所有变量的起点。
let num: number = null;
void 类型:分配给没有返回值的方法的类型。
let unusable: void = undefined;
5、TypeScript 中的变量以及如何声明?
变量是内存中用于存储值的命名空间。
在 TypeScript 中声明变量的类型语法在变量名称后包括一个冒号(:),后跟其类型。 与 JavaScript 相似,我们使用var关键字声明变量。
在Typescript中声明变量时,必须遵循某些规则:
- 变量名称必须是字母或数字。
- 不能以数字开头名称。
- 除下划线( _ )和美元( $ )符号外,它不能包含空格和特殊字符。
6、TypeScript 中的泛型是什么?
TypeScript Generics 是提供创建可重用组件的方法的工具。 它能够创建可以使用多种数据类型而不是单一数据类型的组件。 而且,它在不影响性能或生产率的情况下提供了类型安全性。 泛型允许我们创建泛型类,泛型函数,泛型方法和泛型接口。
在泛型中,类型参数写在左括号(<)和右括号(>)之间,这使它成为强类型集合。 它使用一种特殊的类型变量来表示类型。
function identity < T > (arg: T) : T { return arg; } let output1 = identity < string > ("edureka"); let output2 = identity < number > (117); console.log(output1); console.log(output2);
7、TypeScript 中 interface 和 type 的差别是什么?
7.1、相同点
- 都可以描述一个对象或者函数
interface User { name: string age: number } interface SetUser { (name: string, age: number) : void; } type User = { name: string age: number }; type SetUser = (name: string, age: number) = >void;
- 都允许拓展(extends)
interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说 interface 可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。
// 1、interface extends interface interface Name { name: string; } interface User extends Name { age: number; } // 2、type extends type type Name = { name: string; } type User = Name & { age: number }; // 3、interface extends type type Name = { name: string; } interface User extends Name { age: number; } // 4、type extends interface interface Name { name: string; } type User = Name & { age: number; }
7.2、不同点
- type 可以而 interface 不行
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名 type Name = string // 联合类型 interface Dog { wong(); } interface Cat { miao(); } type Pet = Dog | Cat // 具体定义数组每个位置的类型 type PetList = [Dog, Pet]
type 语句中还可以使用 typeof 获取实例的 类型进行赋值
// 当你想获取一个变量的类型时,使用 typeof let div = document.createElement('div'); type B = typeof div
其他骚操作
type StringOrNumber = string | number; type Text = string | { text: string }; type NameLookup = Dictionary<string, Person>; type Callback<T> = (data: T) => void; type Pair<T> = [T, T]; type Coordinates = Pair<number>; type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
- interface 可以而 type 不行
interface 能够声明合并
interface User { name: string age: number } interface User { sex: string } /* User 接口为 { name: string age: number sex: string } */
一般来说,如果不清楚什么时候用interface/type,能用 interface 实现,就用 interface , 如果不能就用 type 。
8、TypeScript 的主要特点是什么?
- 跨平台:TypeScript 编译器可以安装在任何操作系统上,包括 Windows、macOS 和 Linux。
- ES6 特性:TypeScript 包含计划中的 ECMAScript 2015 (ES6) 的大部分特性,例如箭头函数。
- 面向对象的语言:TypeScript 提供所有标准的 OOP 功能,如类、接口和模块。
- 静态类型检查:TypeScript 使用静态类型并帮助在编译时进行类型检查。因此,你可以在编写代码时发现编译时错误,而无需运行脚本。
- 可选的静态类型:如果你习惯了 JavaScript 的动态类型,TypeScript 还允许可选的静态类型。
- DOM 操作:您可以使用 TypeScript 来操作 DOM 以添加或删除客户端网页元素。
9、TypeScript 中 never 和 void 的区别
- void 表示没有任何类型(可以被赋值为 null 和 undefined)。
- never 表示一个不包含值的类型,即表示永远不存在的值。
- 拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。
10、说一说 TypeScript 中的类及其特性。
TypeScript 引入了类,以便它们可以利用诸如封装和抽象之类的面向对象技术的好处。
TypeScript 编译器将 TypeScript 中的类编译为普通的 JavaScript 函数,以跨平台和浏览器工作。
一个类包括以下内容:
- 构造器(Constructor)
- 属性(Properties)
- 方法(Methods)
class Employee { empID: number; empName: string; constructor(ID: number, name: string) { this.empName = name; this.empID = ID; } getSalary(): number { return 40000; } }
类的其他特性有:
- 继承(Inheritance)
- 封装(Encapsulation)
- 多态(Polymorphism)
- 抽象(Abstraction)
11、TypeScript 中的类型断言是什么?
TypeScript 中的类型断言的工作方式类似于其他语言中的类型转换,但没有 C# 和 Java 等语言中可能的类型检查或数据重组。类型断言对运行时没有影响,仅由编译器使用。
类型断言本质上是类型转换的软版本,它建议编译器将变量视为某种类型,但如果它处于不同的形式,则不会强制它进入该模型。
12、TypeScript 中的模块是什么?
TypeScript 中的模块是相关变量、函数、类和接口的集合。 你可以将模块视为包含执行任务所需的一切的容器。可以导入模块以轻松地在项目之间共享代码。
module module_name{ class xyz{ export sum(x, y){ return x+y; } } }
13、解释如何使用 TypeScript 中的 mixin。
Mixin 本质上是在相反方向上工作的继承。Mixins 允许你通过组合以前类中更简单的部分类设置来构建新类。
相反,类A继承类B来获得它的功能,类B从类A需要返回一个新类的附加功能。
14、TypeScript 中什么是装饰器,它们可以应用于什么?
装饰器是一种特殊的声明,它允许你通过使用@注释标记来一次性修改类或类成员。每个装饰器都必须引用一个将在运行时评估的函数。
例如,装饰器@sealed将对应于sealed函数。任何标有 的@sealed都将用于评估sealed函数。
function sealed(target) { // do something with 'target' ... }
它们可以附加到:
- 类声明
- 方法
- 配件
- 特性
- 参数
注意:默认情况下不启用装饰器。要启用它们,你必须experimentalDecorators从tsconfig.json文件或命令行编辑编译器选项中的字段。
15、使用 ts 实现一个判断入参是否是数组类型的方法?
unknown 用于变量类型不确定,但肯定可以确定的情形下,比如下面这个示例中,入参总归会有个值,根据这个值的类型进行不同的处理,这里使用 unknown 替代 any 则会更加类型安全。
function isArray(x: unknown): boolean { if (Array.isArray(x)) { return true; } return false; }