使用Exclude时出现Type T is not assignable to type 'never'错误如何解决
TypeScript 字段可排序性类型守卫报错修复
问题背景
现有两份列表:所有字段名列表、不可排序字段名列表,需要通过类型推导判断指定字段是否属于不可排序字段的补集(即可排序字段)。
初始代码与报错
最初编写的代码如下:
function isUnsortableField<All extends string | number | symbol, T extends All, K extends Exclude<All, T>>(unsortable: Array<K>, field: All): field is T { return !!unsortable.find((f) => f === field) } const allFields = ['bar', 'zee'] as const; const unsortableOnes: Array<typeof allFields[number]> = ['bar']; const ugh = isUnsortableField(unsortableOnes, 'bar');
运行后触发TS类型报错:
Argument of type '("bar" | "zee")[]' is not assignable to parameter of type 'never[]'. Type 'string' is not assignable to type 'never'. Type 'string' is not assignable to type 'never'.ts(2345)
报错原因
初始泛型定义中,unsortable参数类型被指定为Array<K>,而K是Exclude<All, T>的派生类型,TS无法从入参自动推导出泛型T的实际类型,最终K会被推导为never类型,导致unsortable参数被识别为never[],传入实际的字段数组就会触发类型不兼容错误。
修复方案
将unsortable参数的类型从Array<K>修改为Array<T>(修复后统一调整了泛型命名语义,更易读),修复后代码如下:
function isSortableField< All extends PropertyKey, Unsorted extends All, K extends Exclude<All, Unsorted> >(unsortable: Array<Unsorted>, field: All): field is K { return !unsortable.find((f) => f === field); }
修改后TS可以直接从入参的不可排序字段数组推导出Unsorted泛型的实际类型,Exclude<All, Unsorted>就能正确计算出可排序字段的类型集合,类型守卫可以正常生效。
内容的提问来源于stack exchange,提问作者Paul Felice
相关产品推荐
相关产品推荐

