TypeScript 常见面试问题
1 基础概念问题
Q1: TypeScript和JavaScript的主要区别是什么?
- TypeScript是JavaScript的超集,添加了静态类型系统
- TypeScript需要编译,JavaScript可以直接运行
- TypeScript支持接口、泛型、装饰器等高级特性
- TypeScript提供了更好的IDE支持和开发体验
Q2: interface和type有什么区别?
- interface主要用于定义对象形状,支持声明合并
- type可以定义任何类型,包括联合类型、交叉类型、原始类型等
- interface可以使用extends继承,type可以使用&实现类似效果
- 类可以实现(implements)接口,但不能实现类型别名
- 类型别名不能参与声明合并
Q3: 什么是泛型?为什么需要泛型?
泛型允许创建可重用的组件,这些组件可以处理多种类型而不是单一类型。
typescript
// 没有泛型的问题:失去类型信息或需要重复代码
function identity(arg: any): any { return arg; }
// 使用泛型:保持类型信息
function identity<T>(arg: T): T { return arg; }
2 类型系统问题
Q4: any、unknown和never类型有什么区别?
any: 绕过类型检查,完全失去类型安全unknown: 类型安全的any,使用前必须进行类型检查或断言never: 表示永远不会出现的值,常用于抛出异常或无限循环
Q5: 什么是类型守卫?有哪些类型守卫方式?
类型守卫是运行时检查,用于缩小类型范围。
- typeof守卫:
typeof x === "string" - instanceof守卫:
obj instanceof Array - 自定义类型谓词:
function isFish(pet: Fish | Bird): pet is Fish - in操作符:
"swim" in pet - 字面量类型守卫:
x.type === "success"
Q6: 什么是条件类型?举例说明
条件类型根据条件选择类型:
typescript
type IsString<T> = T extends string ? true : false;
type T1 = IsString<string>; // true
type T2 = IsString<number>; // false
// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type StrOrNumArray = ToArray<string | number>; // string[] | number[]
3 高级特性问题
Q7: 什么是映射类型?内置的映射类型有哪些?
映射类型基于旧类型创建新类型:
typescript
// 内置映射类型
type Partial<T> = { [P in keyof T]?: T[P] };
type Required<T> = { [P in keyof T]-?: T[P] };
type Readonly<T> = { readonly [P in keyof T]: T[P] };
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
type Record<K extends keyof any, T> = { [P in K]: T };
Q8: 在Vue 3中如何最佳实践地使用TypeScript?
- 使用
defineComponent包装组件以获得正确的类型推断 - 使用
PropType为props提供精确的类型 - 使用Composition API,它比Options API有更好的类型支持
- 为reactive和ref提供泛型类型参数
- 使用TypeScript的模块扩充为Vue全局属性添加类型
typescript
// Vue 3 + TypeScript最佳实践示例
import { defineComponent, PropType } from 'vue'
interface User {
id: number
name: string
}
export default defineComponent({
props: {
// 使用PropType进行精确类型定义
user: {
type: Object as PropType<User>,
required: true
},
// 数组类型的props
items: {
type: Array as PropType<User[]>,
default: () => []
}
},
setup(props) {
// ref和reactive的类型推断
const count = ref<number>(0)
const state = reactive({
loading: false,
data: null as User[] | null
})
return { count, state }
}
})
Q9: 如何理解TypeScript中的协变和逆变?
- 协变:子类型可以赋值给父类型(数组、函数返回值)
- 逆变:父类型可以赋值给子类型(函数参数)
- 双变:两者都可以(TypeScript 2.6前函数的默认行为)
- 不变:必须完全匹配
4 工程实践问题
Q10: 如何在现有Vue项目中引入TypeScript?
- 安装必要的依赖:
bash
npm install typescript @vue/tsconfig @types/node --save-dev
npm install vue-tsc --save-dev
- 创建tsconfig.json:
json
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
"compilerOptions": {
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
- 将.js文件重命名为.ts/.vue,逐步修复类型错误
- 为Vue SFC添加
<script lang="ts"> - 使用Volar扩展替代Vetur以获得更好的TypeScript支持
Q11: 如何处理没有类型定义的第三方库?
- 创建声明文件(.d.ts):
typescript
// src/types/untyped-module.d.ts
declare module "untyped-vue-component" {
import { Component } from 'vue'
const component: Component
export default component
}
- 使用
shims-vue.d.ts处理Vue文件:
typescript
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
- 使用
@ts-ignore注释临时跳过特定行 - 提交PR给DefinitelyTyped项目
Q12: TypeScript在Vue项目中有哪些性能优化建议?
- 使用
vue-tsc进行类型检查而不是全量tsc - 在开发时关闭严格模式的部分规则,生产构建时开启
- 使用Vite而不是Webpack,Vite对TypeScript有更好的支持
- 避免在模板中使用复杂的类型断言
- 使用
import type进行类型导入,避免将类型包含在最终包中
5 AI时代下的TypeScript应用
Q13: TypeScript如何提升AI编程助手的效率?
- 类型作为上下文:明确的类型定义让AI能更准确理解代码意图
- 智能补全增强:AI能基于类型系统提供更精准的代码建议
- 错误预防:AI生成的代码在TypeScript编译阶段即可发现潜在问题
- 代码理解辅助:类型注解帮助AI理解复杂业务逻辑
- 重构安全性:AI辅助的重构在类型检查下更安全
Q14: 在AI编程时代,如何设计对AI友好的TypeScript代码?
- 使用明确的接口和类型别名,避免复杂的嵌套类型
- 为函数和方法添加完整的JSDoc注释
- 使用有意义的变量名和函数名
- 保持函数的单一职责,每个函数只做一件事
- 使用枚举和字面量类型代替魔术字符串
typescript
// AI友好的代码示例
/**
* 用户注册函数
* @param userData 用户注册数据
* @returns 注册成功的用户信息
*/
async function registerUser(
userData: UserRegistrationData
): Promise<RegistrationResult> {
// 明确的业务逻辑
if (!isValidEmail(userData.email)) {
throw new ValidationError('Invalid email format')
}
// 清晰的错误处理
try {
const result = await api.post('/register', userData)
return result.data
} catch (error) {
if (error instanceof NetworkError) {
throw new RegistrationError('Network issue, please try again')
}
throw error
}
}
Q15: TypeScript与AI编码结合的未来趋势是什么?
- AI驱动的类型推断:AI自动为JavaScript代码添加类型注解
- 智能重构建议:AI基于类型系统提供安全的代码重构方案
- 代码生成优化:AI生成符合项目类型约定的代码
- 测试用例生成:基于类型信息自动生成测试用例
- 文档自动生成:从类型定义自动生成API文档