1. 使用 TypeScript 时遇到过哪些问题?
- 类型定义复杂:对于复杂的对象或函数,类型定义可能变得冗长且难以维护。
- 第三方库类型支持不全:有些第三方库没有提供完整的类型定义,需要手动补充或使用
any
。 - 类型推断不足:在某些情况下,TypeScript 的类型推断可能不够智能,需要手动指定类型。
- 编译速度慢:对于大型项目,TypeScript 的编译速度可能较慢。
- 与 JavaScript 生态的兼容性:有时需要处理 JavaScript 代码与 TypeScript 类型系统的兼容性问题。
2. TypeScript 和 JavaScript 的区别
- 类型系统:
- TypeScript 是 JavaScript 的超集,增加了静态类型系统。
- JavaScript 是动态类型语言,类型在运行时确定。
- 编译:
- TypeScript 需要编译为 JavaScript 才能运行。
- JavaScript 可以直接在浏览器或 Node.js 中运行。
- 工具支持:
- TypeScript 提供了更好的代码提示、类型检查和重构支持。
- JavaScript 的工具支持相对较弱。
- 兼容性:
- TypeScript 完全兼容 JavaScript,可以直接使用现有的 JavaScript 代码。
3. TypeScript 可以定义全局变量,不指定具体类型吗?
可以。可以使用 declare
关键字定义全局变量,并且不指定具体类型(默认为 any
)。
declare var globalVar: any; // 不指定具体类型
4. TypeScript 可以直接运行吗?
不可以。TypeScript 需要先编译为 JavaScript,然后才能运行。可以使用 tsc
编译工具或 ts-node
直接运行 TypeScript 代码。
5. type
和 interface
有什么区别?
- 扩展性:
interface
可以通过extends
扩展。type
可以通过交叉类型(&
)扩展。
- 合并:
- 同名的
interface
会自动合并。 - 同名的
type
会报错。
- 同名的
- 适用场景:
interface
更适合定义对象形状。type
更适合定义联合类型、交叉类型或复杂类型。
6. 多个同名 interface
可以合并吗?
可以。TypeScript 会自动合并同名的 interface
。
interface User {
name: string;
}
interface User {
age: number;
}
const user: User = {
name: 'Alice',
age: 25,
};
7. 用 TypeScript 实现函数 caller
,接收一个函数作为第一个参数,其返回参数类型由接收的函数参数决定
function caller<T extends (...args: any[]) => any>(fn: T, ...args: Parameters<T>): ReturnType<T> {
return fn(...args);
}
// 示例
const add = (a: number, b: number): number => a + b;
const result = caller(add, 1, 2); // result 的类型为 number
8. 用过 TypeScript 的工具类型吗?
TypeScript 提供了许多内置的工具类型,常用的包括:
Partial<T>
:将T
的所有属性变为可选。Required<T>
:将T
的所有属性变为必选。Readonly<T>
:将T
的所有属性变为只读。Record<K, T>
:创建一个键为K
、值为T
的对象类型。Pick<T, K>
:从T
中选取部分属性K
。Omit<T, K>
:从T
中排除部分属性K
。Exclude<T, U>
:从T
中排除可以赋值给U
的类型。Extract<T, U>
:从T
中提取可以赋值给U
的类型。NonNullable<T>
:从T
中排除null
和undefined
。ReturnType<T>
:获取函数T
的返回值类型。Parameters<T>
:获取函数T
的参数类型。
interface User {
name: string;
age: number;
email?: string;
}
type PartialUser = Partial<User>; // 所有属性变为可选
type ReadonlyUser = Readonly<User>; // 所有属性变为只读
type UserNameAndAge = Pick<User, 'name' | 'age'>; // 只选取 name 和 age
type UserWithoutEmail = Omit<User, 'email'>; // 排除 email