能否实现类型安全函数:从联合类型数组筛选单一类型数组?
实现类型安全的联合类型数组过滤函数
完全可以实现,核心是结合类型守卫函数与泛型,解决你原代码中试图在运行时判断泛型类型的问题(TypeScript类型在运行时会被擦除,无法直接通过T extends Book这类语法判断)。
以下是两种可行的实现方案:
方案一:通用型过滤函数(推荐)
通过传入类型守卫函数,让泛型自动推断目标类型,同时保证运行时过滤逻辑的正确性:
interface Book { age: number; pages: number; } interface Rock { age: number; shape: string; } // 定义互斥的联合类型(可选的never字段让类型约束更严格) type BookOrRock = (Book & { shape?: never }) | (Rock & { pages?: never }); // 类型守卫:判断是否为Book const isBook = (x: BookOrRock): x is Book => 'pages' in x; // 类型守卫:判断是否为Rock const isRock = (x: BookOrRock): x is Rock => 'shape' in x; // 通用过滤函数 const filterByType = <T extends BookOrRock>( array: BookOrRock[], typeGuard: (item: BookOrRock) => item is T ): T[] => { const filtered: T[] = []; for (const item of array) { if (typeGuard(item)) { filtered.push(item); } } return filtered; }; // 测试用例 const booksAndRocks: BookOrRock[] = [ { age: 1, pages: 100 }, { age: 1e9, shape: 'round' }, ]; // 自动推断为Rock[]类型 const rocks = filterByType(booksAndRocks, isRock); // 自动推断为Book[]类型 const books = filterByType(booksAndRocks, isBook);
核心逻辑说明:
- 类型守卫函数
isBook/isRock同时承担运行时类型判断和编译时类型推断的作用,告诉TypeScript如何识别目标子类型。 - 泛型
T会根据传入的类型守卫自动推导,返回的数组类型严格对应T[],完全满足类型安全要求。
方案二:重载函数(简化调用)
如果希望通过指定类型标识而非传入守卫函数来调用,可以用函数重载实现:
// 复用之前的接口、联合类型和类型守卫 // 函数重载签名:指定不同调用场景的返回类型 function getOnlyBooksOrOnlyRocks(array: BookOrRock[]): Book[]; function getOnlyBooksOrOnlyRocks(array: BookOrRock[], type: 'book'): Book[]; function getOnlyBooksOrOnlyRocks(array: BookOrRock[], type: 'rock'): Rock[]; // 函数实现 function getOnlyBooksOrOnlyRocks( array: BookOrRock[], type: 'book' | 'rock' = 'book' ): Book[] | Rock[] { const filtered: (Book | Rock)[] = []; for (const item of array) { if ((type === 'book' && isBook(item)) || (type === 'rock' && isRock(item))) { filtered.push(item); } } return filtered as Book[] | Rock[]; } // 使用示例 const rocks = getOnlyBooksOrOnlyRocks(booksAndRocks, 'rock'); // 类型为Rock[] const books = getOnlyBooksOrOnlyRocks(booksAndRocks); // 类型为Book[]
这种方式通过重载签名让编译器根据传入的type参数自动推断返回类型,调用更简洁。
内容的提问来源于stack exchange,提问作者anotherOne
相关产品推荐
相关产品推荐

