TS
Typescript 面试�?
Typescript 已经全面普及,尤其大厂大型项目,前端熟悉 Typescript 是标配�?
::: tip
如有疑问,可免费 加群 讨论咨询,也可参�?1v1 面试咨询服务�?专业、系统、高效、全流程 准备前端面试
:::
TS 优缺点,使用场景
参考答�?
::: details
优点
静态类型,减少类型错误
有错误会在编译时提醒,而非运行时报�?—�?解释“编译时”和“运行时�?- 智能提示,提高开发效�?
缺点学习成本�?- 某些场景下,类型定义会过于混乱,可读性不好,如下代码
使用不当会变�?anyscript
1 | type ModelFieldResolver<T, TKey extends keyof T = any> = ( |
适用场景
- 大型项目,业务复杂,维护人员�?- 逻辑性比较强的代码,依赖类型更多
- 组内要有一个熟�?TS 的架构人员,负责代码规范和质�?
:::
PS. 虽然 TS 有很多问题,网上也有很多“弃�?TS”的说法,但目前 TS 仍然是最优解,而且各大前端框架都默认使�?TS �?
TS 基础类型有哪�?
参考答�?
::: details
- boolean
- number
- string
- symbol
- bigint
- Enum 枚举
- Array 数组
- Tuple 元祖
- Object 对象
- undefined
- null
- any void never unknown
:::
参考资�?
::: details
:::
数组 Array 和元�?Tuple 的区别是什�?
参考答�?
::: details
数组元素只能有一种类型,元祖元素可以有多种类型�?
1 | // 数组,两种定义方�?const list1: number[] = [1, 2, 3] |
:::
枚举 enum 是什么?有什么使用场景?
JS 中没�?enum 枚举,只学过 JS 你可能不知道 enum 。其实在 Java �?C# 等高级语言中早就有了,TS 中也有�?
参考答�?
::: details
enum 枚举,一般用于表示有限的一些选项,例如使�?enum 定义 4 个方�?
1 | enum Direction { |
其他代码中,我们可以获取某一个方向,用于展示或存储。这样代码更具有可读性和维护行�?
1 | const d = Direction.Up |
:::
参考资�?
::: details
:::
keyof �?typeof 有什么区别?
参考答�?
::: details
typeof �?JS 基础用法,用于获取类型,这个很简单�?keyof �?TS 语法,用于获取所�?key 的类型,例如
1 | interface Person { |
可以把代码拷贝到这里来练�?https://www.tslang.cn/play/index.html
:::
参考资�?
::: details
:::
any void never unknown 有什么区�?
参考答�?
::: details
主要区别�?
any任意类型(不进行类型检查)void没有任何类型,和any相反never永不存在的值的类型unknown未知类型(一个更安全�?any�?
代码示例
1 | function fn(): void {} // void 一般定义函数返回�? |
:::
追问:# �?private 有什么区别呢�?
::: details
# �?TS 中可定义私有属�?
1 | class Person { |
区别�?
#属性,不能在参数中定义private属性,可通过as any强制获取#属性,更私�?
:::
type �?interface 共同和区别,如何选择
type �?interface 有很多相同之处,很多人因此而产生“选择困难症”,这也�?TS 热议的话题�?
共同�?
::: details
- 都能描述一个对象结�?- 都能�?class 实现
- 都能被扩�?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 接口
interface User {
name: string
age: number
getName: () => string
}
// 自定义类�?type UserType = {
name: string
age: number
getName: () => string
}
// class UserClass implements User {
class UserClass implements UserType {
name = 'x'
age = 20
getName() {
return this.name
}
}
:::
区别
::: details
- type 可以声明基础类型
- type 有联合类型和交差类型
- type 可以�?
typeof赋�?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// type 基础类型
type name = string
type list = Array<string>
// type 联合类型
type info = string | number
type T1 = { name: string }
type T2 = { age: number }
// interface T2 { age: number } // 联合,还可以�?interface ,乱�?..
type T3 = T1 | T2
const a: T3 = { name: 'x' }
type T4 = T1 & T2
const b: T4 = { age: 20, name: 'x' }
// typeof 获取
type T5 = typeof b
//【补充】还有个 keyof ,它�?typeof 完全不同,它是获�?key 类型�?type K1 = keyof T5
const k: K1 = 'name'
:::
如何选择�?
::: details
根据社区的使用习惯,推荐使用方式
- 能用 interface 就尽量用 interface
- 除非必须�?type 的时候才�?type
:::
参考资�?
::: details
:::
PS. 其实你混�?type �?interface 不是你的问题,这�?TS 设计的问题,或者说 TS 设计初衷和后来演变带来的副作用�?
什么是泛型,如何使用它�?
只学�?JS 的同学不知道泛型,其实它早就�?C# �?Java 中的重要概念了。初学泛型可能会比较迷惑,需要多些代码多练习�?
泛型的定�?
::: details
泛型 Generics 即通用类型,可以灵活的定义类型而无需写死�?
1 | const list: Array<string> = ['a', 'b'] |
:::
泛型的使�?
::: details
- 用于函数
1 | // Type 一般可简写为 T |
- 用于 class
1 | class SomeClass<T> { |
- 用于 type
1 | function fn<T>(arg: T): T { |
- 用于 interface
1 | // interface F1 { |
:::
参考资�?
::: details
:::
什么是交叉类型和联合类�?
交叉类型 T1 & T2
交叉类型是将多个类型合并为一个类型,包含了所需的所有类型的特性。例�?T1 & T2 & T3
代码示例
::: details
1 | interface U1 { |
:::
注意事项
::: details
- 两个类型的相同属性,如果类型不同(冲突了),则该属性是
never类型
1 | // 如上代码 |
- 基础类型没办法交叉,会返�?
never
1 | type T = string & number // never |
:::
参考资�?
::: details
:::
联合类型 T1 | T2
一种“或”的关系。格式如 T1 | T2 | T3。代码示例如�?
::: details
1 | interface U1 { |
:::
注意事项
::: details
基础类型可以联合
1 | type T = string | number |
但如果未赋值的情况下,联合类型无法使用 string �?number 的方�?
1 | function fn(x: string | number) { |
:::
参考资�?
::: details
:::
是否用过工具类型
TS 工具类型�?Partial Required Omit ReadOnly 等,熟练使用 TS 的人都会熟悉这些工具类型�?
参考答�?
::: details
Partial<T> 属性设置为可�?
1 | interface User { |
Require<T> 属性设置为必�?(和 Partial 相反�?Pick<T, K> 挑选部分属�?
1 | interface User { |
Omit<T, K> 剔除部分属性(�?Pick 相反�?ReadOnly<T> 属性设置为只读
相当于为每个属性都设置一�?readonly
1 | interface User { |
:::
TS 这些符号 ? ?. ?? ! _ & | # 分别什么意�?
参考答�?
::: details
? 可选属性,可选参�?
1 | interface User { |
?. 可选链:有则获取,没有则返�?undefined ,但不报错�?
1 | const user: any = { |
?? 空值合并运算符:当左侧的操作数�?null 或�?undefined 时,返回其右侧操作数,否则返回左侧操作数�?
1 | const user: any = { |
! 非空断言操作符:忽略 undefined null ,自己把控风�?
1 | function fn(a?: string) { |
_ 数字分隔符:分割数字,增加可读�?
1 | const million = 1_000_000 |
:::
参考资�?
::: details
- https://www.tslang.cn/docs/handbook/classes.html 其中搜索
abstract class
:::
如何扩展 window 属性,如何定义第三方模块的类型
参考答�?
::: details
1 | declare interface Window { |
:::
是否有过真实�?Typescript 开发经验,讲一下你的使用体�?
开放性问题,需要结合你实际开发经验来总结。可以从以下几个方面考虑
::: details
- �?Vue React 或其他框架使用时遇到的障碍?
- 在打包构建时,有没有遇到 TS 语法问题而打包失败?
- 有没有用很多
any?如何避�?any泛滥�?
:::
参考资�?
::: details
:::