面试题答案
一键面试1. 类型定义共享方式
- 独立类型库:创建一个独立的 npm 包,专门用于存放跨应用共享的类型定义。每个子应用通过安装该包来获取共享类型。例如,创建
@company/shared-types
包,将通用类型定义如用户信息、接口响应结构等放在这个包中。这样不同子应用无论其 TypeScript 版本如何,都基于同一个来源的类型定义,减少类型冲突可能性。 - 构建时生成:在构建过程中,通过工具(如
tsc
结合自定义脚本)从各个子应用中提取出共享类型,并生成一个统一的类型定义文件(.d.ts
)。然后将这个文件发布到一个共享位置(如内部 npm 仓库)供所有子应用使用。
2. 解决类型冲突
- 命名空间隔离:在共享类型库中,为不同来源或功能的类型使用命名空间进行隔离。例如,对于用户相关类型放在
UserNamespace
命名空间下,订单相关类型放在OrderNamespace
下。这样即使不同子应用对某些类型有类似命名,也不会冲突。 - 版本控制:在共享类型库的
package.json
中严格管理版本,当类型发生变化时,按照语义化版本规则更新版本号。子应用在更新共享类型库版本时,通过代码审查确保类型变化不会导致冲突。如果有潜在冲突,及时调整子应用代码以适配新类型。
3. 动态类型调整
- 运行时类型断言:在需要根据运行时环境动态调整类型的地方,使用 TypeScript 的类型断言。例如,假设根据环境变量判断是否为管理员用户,代码如下:
let user: UserType;
if (process.env.IS_ADMIN === 'true') {
user = { name: 'admin', role: 'admin' } as AdminUserType;
} else {
user = { name: 'user', role: 'user' } as RegularUserType;
}
- 类型映射函数:创建类型映射函数,根据运行时环境返回不同类型。例如:
function getUserType(env: string): UserType {
if (env === 'admin') {
return { name: 'admin', role: 'admin' } as AdminUserType;
}
return { name: 'user', role: 'user' } as RegularUserType;
}
然后在应用中调用这个函数获取动态类型。
4. 与不同 TypeScript 版本兼容性
- 使用兼容的类型特性:在共享类型库中,避免使用高版本 TypeScript 独有的特性,尽量使用各版本都支持的基础类型特性。例如,避免使用 TypeScript 4.0 以上才有的
template literal types
等特性,如果必须使用,针对低版本可以通过 polyfill 或者替代方案解决。 - 编译目标设置:在构建共享类型库时,将
tsconfig.json
中的target
设置为较低版本,如es5
或es6
,确保生成的类型定义文件在各子应用不同 TypeScript 版本下都能正常使用。同时,在子应用中,如果其 TypeScript 版本较高,可以在tsconfig.json
中配置allowSyntheticDefaultImports
等选项,以更好地兼容共享类型库。