TypeScript中泛型结合断言谓词过滤数组时的报错问题
类型谓词函数的类型兼容性错误问题
我写了一个用于数组过滤的断言谓词函数,代码如下:
const isNotEmptyName = <T extends { name: string | null }>(value: T): value is { name: string } => Boolean(value.name);
但出现了如下错误提示:
类型谓词的类型必须可分配给其参数的类型。 类型“{ name: string; }”不可分配给类型“T”。 “{ name: string; }”可分配给“T”的约束类型,但“T”可以用约束“{ name: string | null; }”的不同子类型实例化。
错误原因
你的类型谓词value is { name: string }和泛型参数T不兼容。T是{ name: string | null }的子类型,它可能包含name之外的其他属性,或者name是更具体的子类型。而{ name: string }是固定类型,无法保证能分配给任意T实例——比如如果T是{ name: string | null; age: number },断言成{ name: string }会丢失age属性,不符合T的结构,因此TypeScript报错。
正确写法
要让类型谓词和T兼容,需断言value是T的子类型:保留T的所有属性,仅将name的类型缩小为string。
写法一(直接交集类型)
const isNotEmptyName = <T extends { name: string | null }>(value: T): value is T & { name: string } => Boolean(value.name);
写法二(利用类型排除)
const isNotEmptyName = <T extends { name: string | null }>(value: T): value is T & { name: Exclude<T['name'], null> } => Boolean(value.name);
使用示例
interface User { name: string | null; age: number; } const users: User[] = [ { name: 'Alice', age: 25 }, { name: null, age: 30 }, { name: 'Bob', age: 28 } ]; const validUsers = users.filter(isNotEmptyName); // validUsers 类型为 (User & { name: string })[],即 { name: string; age: number }[]
内容的提问来源于stack exchange,提问作者Uzakov Nikita
相关产品推荐
相关产品推荐

