TS相关面试题
1.interface和type的区别
声明合并
interface支持声明合并:可以多次定义同名的接口TypeScript会自动合并这些定义
interface User {
name: string;
}
interface User {
age: number;
}
// 最终 User 接口包含 name 和 age
type 不支持申明合并:重复定义同名的type会报错
适用范围
interface主要用于定义对象类型
type可以为任何类型创建别名
// 原始类型别名
type ID = string | number;
// 函数类型
type Callback = () => void;
// 元组类型
type Point = [number, number];
// 联合类型
type Status = 'active' | 'inactive';
扩展方式
interface使用extends关键字:
interface Animal {
name:string
}
interface Dog extends Animal {
breed:string
}
type使用交叉类型 &:
type Animal = {
name:string
}
type Dog = Animal & {
breed:string
}
类实现
interface 更适合类实现
interface Logger {
log(message:string):void
}
class ConsoleLogger implements Logger{
log(message:string){
console.log(message)
}
}
type 也可以用于类实现,但通常不是首选方式
高级类型
type 支持更复杂的类型操作:
//映射类型
type Readonly<T> = {
readonly [P in keyof T]:T[P]
}
//条件类型
type NonNullable<T> = T extends null | undefined?never:T
//实用工具类型
type PartialUser = Partial<User>
使用interface的情况
- 定义对象的形状(尤其是公共API)
- 需要声明合并的场景
- 类实现(implemennts)
- 当你想要更清晰的错误信息时
使用type的情况
- 创建类型别名(原始类型,联合类型等)
- 定义元组类型
- 使用映射类型,条件类型
- 需要组合多个类型(交叉类型)
TypeScript泛型核心概念详解
1.泛型基础
泛型是Ts中的类型参数,允许我们创建可复用的组件,这些组件可以支持多种类型而不丢失类型安全性
// 基本泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 使用
let output = identity<string>("Hello"); // 显式指定类型
let output2 = identity("Hello"); // 类型推断
2.泛型约束
使用extends关键字约束泛型参数必须满足特定条件:
interface Lengthwise {
length:number
}
function loggingIdentity<T extends Lengthwise>(arg:T):T{
return arg
}
//有效调用
loggingIdentity('Hello') //字符串有length属性
loggingIdentity([1,2,3,4])//数组有length熟悉
//无效调用
loggingIdentity(3) //错误 - 数字没有length熟悉
3.内置实用工具类型
| 工具类型 | 描述 |
|---|---|
| Partial<T> | 使T的所有属性变为可选 |
| Require<T> | 使T的所有熟悉变为必须 |
| Readonly<T> | 使T的所有熟悉变为只读 |
| Pick<T,K> | 从T中选取部分属性K |
| Omit<T,K> | 从T中排出部分熟悉K |
| Record<K,T> | 构造键类型为K,值类型为T的对象类型 |
| Exclude<T,U> | 从T中排除可分配给U的类型 |
| Extract<T,U> | 从T中提取可分配到U的类型 |
高级泛型技术
条件类型
基于条件表达式选择类型
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
"object";
type T0 = TypeName<string>; // "string"
type T1 = TypeName<true>; // "boolean"
映射类型
基于旧类型创建类型
type Optional<T> = {
[P in keyof T]?: T[P];
};
interface Person {
name: string;
age: number;
}
type OptionalPerson = Optional<Person>;
// { name?: string; age?: number; }
泛型默认值
为泛型参数提供默认类型
interface Pagination<T = any> {
data: T[];
page: number;
pageSize: number;
total: number;
}
// 使用默认类型
const pagination: Pagination = { ... };
// 指定类型
const userPagination: Pagination<User> = { ... };
泛型的最佳实践
- 命名约定: 使用有意义的单字母(T,K,V)或描述性名称(TData,TKey)
- 类型约束: 使用 extends 添加必要的约束
- 默认值: 为常用泛型提供合理的默认类型
- 文档: 为复杂泛型添加文档说明
- 避免过度使用: 只在真正需要灵活性的地方使用泛型
- 优先使用内置工具类型: 减少重复造轮子