面试题答案
一键面试1. 定义泛型函数 filter
function filter<T, U extends T>(arr: T[], typeGuard: (arg: T) => arg is U): U[] {
return arr.filter(typeGuard);
}
思路:
- 该函数接收两个参数,一个是数组
arr
,其类型为T
数组,另一个是类型保护函数typeGuard
,它用于判断T
类型的元素是否为U
类型(U
是T
的子类型)。 - 函数内部使用数组的
filter
方法,传入typeGuard
函数,这样就可以过滤出满足typeGuard
条件的元素,返回类型为U
数组。
2. 编写使用场景及结合条件类型处理复杂逻辑
type Animal = { name: string };
type Dog = Animal & { bark: () => void };
type Cat = Animal & { meow: () => void };
function isDog(animal: Animal): animal is Dog {
return (animal as Dog).bark!== undefined;
}
function isCat(animal: Animal): animal is Cat {
return (animal as Cat).meow!== undefined;
}
function handleAnimal(animal: Animal) {
if (isDog(animal)) {
animal.bark();
} else if (isCat(animal)) {
animal.meow();
} else {
console.log(`${animal.name} is an unknown animal`);
}
}
const animals: Animal[] = [
{ name: 'Buddy', bark: () => console.log('Woof') },
{ name: 'Whiskers', meow: () => console.log('Meow') },
{ name: 'Toby' }
];
const dogs = filter(animals, isDog);
const cats = filter(animals, isCat);
dogs.forEach(handleAnimal);
cats.forEach(handleAnimal);
思路:
- 首先定义了
Animal
类型,它有一个name
属性。然后定义了Dog
和Cat
类型,它们继承自Animal
并分别有自己的方法bark
和meow
。 - 接着定义了
isDog
和isCat
两个类型保护函数,用于判断Animal
类型的元素是否为Dog
或Cat
类型。 handleAnimal
函数展示了如何根据不同类型执行不同逻辑,利用isDog
和isCat
类型保护函数进行判断。- 创建了一个
Animal
数组animals
,其中包含Dog
、Cat
和普通Animal
类型的元素。 - 使用
filter
函数分别过滤出Dog
和Cat
类型的元素,存储在dogs
和cats
数组中。 - 最后对
dogs
和cats
数组分别调用handleAnimal
函数,根据元素类型执行不同操作。
TypeScript类型系统的作用机制
- 泛型:在
filter
函数定义中,T
和U
泛型允许我们在函数定义时不指定具体类型,而是在使用时确定。这样提高了函数的复用性,使其可以处理各种类型的数组。 - 类型保护:
isDog
和isCat
函数通过返回类型谓词(animal is Dog
和animal is Cat
)告诉TypeScript编译器,在函数返回true
时,传入的animal
参数实际上是Dog
或Cat
类型,从而在后续代码中可以安全地访问Dog
或Cat
特有的属性和方法。 - 条件类型:虽然在这个例子中没有显式使用条件类型的语法(如
T extends U? X : Y
),但类型保护机制本质上是一种隐式的条件类型判断。在handleAnimal
函数中,通过isDog
和isCat
进行条件判断,TypeScript编译器会根据判断结果,智能地推断出animal
的具体类型,从而确保类型安全。