TypeScript单属性投影函数报错:Projection类型赋值问题
解决TypeScript中
project_one_property的类型错误问题 这个问题我之前也碰到过,TypeScript在这里的类型推断确实有点严格,咱们一步步拆解原因和解决方案:
为什么会报错?
你遇到的类型错误,本质是TypeScript对动态键名创建对象的类型推断规则导致的:
当你用{ [propertyName]: 1 }这种方式创建对象时,TypeScript没办法自动识别出这个对象符合Projection<T>的类型——它会默认把这个对象推断成{ [x: string]: number }(最宽泛的字符串索引类型)。而Projection<T>要求键必须是keyof T的子集,所以这两个类型不兼容,就抛出了类型错误。
三种可行的修改方案
方案1:使用类型断言(最直接)
手动告诉TypeScript,这个动态创建的对象确实符合Projection<T>的类型,用as关键字做类型断言:
const project_one_property = function<T, K extends keyof T>(object: T, propertyName: K): Partial<T> { // 直接断言为Projection<T>,快速解决问题 const projection: Projection<T> = { [propertyName]: 1 } as Projection<T>; return project(object, projection); };
如果想让类型更精准,也可以断言成Record<K, 1>(明确键是K类型,值为1),避免过度断言:
const projection = { [propertyName]: 1 } as Record<K, 1>;
方案2:用Object.defineProperty构建对象(更安全)
如果你不想用类型断言,也可以通过Object.defineProperty来添加属性,TypeScript能更好地跟踪键的类型:
const project_one_property = function<T, K extends keyof T>(object: T, propertyName: K): Partial<T> { const projection: Projection<T> = {}; // 明确指定给projection添加的键是K类型,TypeScript能自动匹配类型 Object.defineProperty(projection, propertyName, { value: 1 }); return project(object, projection); };
这种方式不需要额外断言,完全依赖TypeScript的类型推导,安全性更高。
方案3:利用TypeScript类型工具显式声明
用Pick工具类型明确指定projection的键范围,再转为Projection<T>:
const project_one_property = function<T, K extends keyof T>(object: T, propertyName: K): Partial<T> { // 显式声明只选取K对应的键 const projection: Pick<Projection<T>, K> = { [propertyName]: 1 }; return project(object, projection as Projection<T>); };
这种方式更清晰地表达了代码意图,适合对类型严谨性要求较高的场景。
内容的提问来源于stack exchange,提问作者Shaun Xu
相关产品推荐
相关产品推荐

