面试题答案
一键面试类型别名
类型别名可以为复杂类型创建一个简洁的名称,方便在函数参数和返回值中使用。
// 定义一个复杂的嵌套对象类型别名
type ComplexObject = {
nested: {
value: string | number;
subNested: {
flag: boolean;
data: { [key: string]: any };
}[];
};
};
// 使用类型别名作为函数参数和返回值类型
function processComplexObject(obj: ComplexObject): string {
return JSON.stringify(obj);
}
接口定义
接口用于定义对象的形状,对于函数参数和返回值类型的定义非常清晰。
// 定义一个接口
interface ComplexInterface {
nested: {
value: string | number;
subNested: {
flag: boolean;
data: { [key: string]: any };
}[];
};
}
// 使用接口作为函数参数和返回值类型
function processComplexInterface(obj: ComplexInterface): string {
return JSON.stringify(obj);
}
泛型约束
当函数的逻辑不依赖于具体类型,但需要对类型进行约束时,泛型非常有用。
// 定义一个泛型函数,约束T必须包含length属性
function printLength<T extends { length: number }>(arg: T): void {
console.log(arg.length);
}
// 使用泛型函数
printLength('hello');
printLength([1, 2, 3]);
结合使用
在实际项目中,往往会结合多种方式来管理类型。
// 定义一个泛型接口
interface GenericInterface<T> {
data: T;
process: () => string;
}
// 定义一个类型别名
type SpecificType = { name: string; age: number };
// 实现泛型接口
class GenericClass<T> implements GenericInterface<T> {
constructor(public data: T) {}
process(): string {
return JSON.stringify(this.data);
}
}
// 使用类型别名和泛型类
let instance = new GenericClass<SpecificType>({ name: 'John', age: 30 });
console.log(instance.process());
通过以上策略,可以有效地管理复杂的类型推断,提高代码的可读性和可维护性。