1. 如何理解TS中的any、unknow和never?
any 支持几乎任何类型,不包含never、unknown、void。
unknow 表示尚不清楚的类型,但可以表示所有类型的联合。当一个值是从外部获取的不能提前知道类型,等使用的时候我们再去做断言类型操作。
never 不包含任何元素,空集。当在处理异常和错误情况时,never可以表示该变量为不应该出现的类型。
2. type和interface有什么区别?
type 类型别名
interface 声明接口(ts的interface描述一个对象的属性,java c#中的interface为描述功能)
interface用面向对的方式解释type,关键词extends 相当于type中联合类型
区别1:
type 可以描述所有数据:基本类型和对象
interface 只能描述对象
区别2:
type 只是类型的别名(ts会推导出已存在的类型)
interface 则是声明类型(interface会创建一个新的类型)
区别3:
type不可以重新赋值
而interface会自动合并,可以进行字段扩展(理解:描述对象的时候可以加一个属性)
所以对外API尽量使用interface,方便扩展。
对内API尽量使用type,防止代码分散。
interface Person {
name: string
}
interface Person {
age: number
}
区别4:
interface在extends时如果有属性冲突会直接报错(报错更明显)
而type不会报错,会将该属性的类型变为never,甚至直接把当前type变为never
3. 联合类型变量在使用时怎么类型收窄?(什么是类型收窄?)
联合类型变量在定义的时候是多个类型的并集,在使用的时候需要区分类型(类型收窄 narrowing)
- 用typeof(有局限,数组对象、普通对象、日期对象、null,typeof都返回object)
- 使用instanceof区分类型(有局限,不支持string、number、boolean、TS独有类型)
- 结合1和2,普通类型使用typeof,对象类型使用instanceof(局限:TS类型无法区分)
- 在3的基础上,使用keyA in TypeA,关键词in来区分TS类型
- 以上4点都是使用js的方法来区分类型,可以使用TS的类型谓词is来判断任意类型(支持所有类型,但比较麻烦需要声明一个函数)
|
|
- 自己在对象类型中添加一个可识别字段,比如kind: ‘xx’,我定义圆形类型的kind一定为circle,方形类型的kind一定为rect,这样就可以通过kind来区分类型了。一般使用kind、type,要求所有要区分的类型都有kind字段;是kind需要时基本类型;各类型间的kind可区分。
4. 当交叉类型有字段类型冲突的时候,该字段会是什么类型?
答案是never。
例如:
type A = {
age: number;
}
type B = {
age: string;
}
type C = A & B;
const c: C = {
age: '123' // age的类型是never
}
5. 如何断言绑定事件的回调函数?
|
|
或者 在tsconifg中把straictFunctionTypes设置为false
或者用 as unknown as xxx
6. as const 怎么使用?
as const 可以用来收紧类型。
|
|
7. ts有哪些语法可以从类型中创造新类型?
extends 包含于
keyof 获取一个对象类型的所有key
T[‘name’] 获取类型T中下标为name的类型,其中name extends keyof T
in keyof 主要在map类型中使用
-readonly[] 使得对应类型从只读变为可操作
-? 使得可选类型变为必填类型
as 断言操作,对一个类型做进一步的判断
8. interface和class的区别?
interface只有成员类型没有实现
普通class必须有成员的类型和实现
abstract class(抽象类)的成员类型可以实现也可以不实现
所以class一般用于实现interface,而且一个class可以同时实现多个interface
ps: 在class中也可以使用索引签名
|
|
9. 什么是infer?
infer可以显式地声明一个泛型变量。这样描述很抽象来看例子:
|
|
10. 类型声明文件和类型作用域有什么关系?
默认情况下*.d.ts中的type和interface全局生效,
但是如果*.d.ts文件中有import或者export则type和interface只在当前模块生效,
此时可以用declare global包裹type和interface使其全局生效;
当为js文件写类型声明文件时,如果是全局作用域的类型则可以直接对应js文件中的变量和函数,如果是局部作用域的类型则可以用declare module包裹或者用同名文件(如下);
main.js
main.d.js
同名文件可以有一一对应的关系,可以视作在一个作用域中.
11 全局变量中的document和Element类型是谁声明的?
我们可以在tsconfig中的compilerOptions.lib中添加DOM来支持DOM相关方法的类型.
相同的全局变量中的Object,Array,Set,Map…是由ESNext来支持相关类型的.
默认会加载@types包下所有的类型文件,如果需要指定加载的类型文件可以在tsconfig中的compilerOptions.types中指定.