TS编译器为何认为值可能是{}?如何解决该类型赋值报错
TypeScript泛型函数类型错误分析与解决
一、& {}的来源解释
报错里的& {}是TypeScript处理非空判断时的内部类型缩小逻辑:
当你通过if (objId === undefined || objId === null)排除了null和undefined后,TypeScript会用& {}来过滤掉这两个空值类型(因为null & {}和undefined & {}都会被解析为never)。但在泛型上下文里,TypeScript没办法自动推导出去掉空值后的类型就是MyId,所以它只能用T[MyIdProp<T>] & {}来表示非空的属性值类型,而这个类型和MyId之间没有被TypeScript识别为可赋值的关系,因此触发了2322错误。
二、解决方法
这里提供三种可行的解决方式,按需选择:
1. 类型断言快速解决
既然你已经通过代码逻辑确保了objId不是null或undefined,直接用类型断言告诉TypeScript它就是MyId即可:
function doSomething<T extends object>(obj: T, idAttr: MyIdProp<T>): MyId { const objId = obj[idAttr]; if (objId === undefined || objId === null) { throw new Error('No ID supplied!'); } return objId as MyId; }
2. 优化MyIdProp的类型定义
调整类型定义,让TypeScript更清晰地关联属性类型与MyId的关系:
export type MyId = string | number; // 明确筛选值为MyId或undefined的属性键 export type MyIdProp<T extends object> = { [K in keyof T]: T[K] extends MyId | undefined ? K : never }[keyof T]; // 定义非空ID的类型 type NonNullableMyId<T extends object> = Exclude<T[MyIdProp<T>], null | undefined>; function doSomething<T extends object>(obj: T, idAttr: MyIdProp<T>): MyId { const objId = obj[idAttr]; if (objId === undefined || objId === null) { throw new Error('No ID supplied!'); } return objId as NonNullableMyId<T>; }
3. 用where子句强化泛型约束(推荐,TypeScript 4.7+)
利用TypeScript的where子句直接约束属性类型,让TypeScript自动推导非空后的类型:
export type MyId = string | number; function doSomething<T extends object, K extends keyof T>( obj: T, idAttr: K ): MyId where T[K] extends MyId | undefined { const objId = obj[idAttr]; if (objId === undefined || objId === null) { throw new Error('No ID supplied!'); } return objId; // 此处无需断言,TypeScript可正确识别类型 }
内容的提问来源于stack exchange,提问作者F-H
相关产品推荐
相关产品推荐

