从泛型对象移除非函数属性并在泛型类中使用的TS问题
问题分析与解决方案
错误原因
你遇到的TS2322错误本质源于两点:
- 泛型
T没有类型约束,TypeScript认为它可以是任意类型(比如number、string这类基本类型),当block.genericObject为undefined时,展开后的{}无法赋值给非对象类型的T。 block.genericObject的类型是NonFunctionProperties<T>(T的非函数属性子集),而this.genericObject是完整的T类型,TypeScript无法自动识别子集到父集的赋值合法性,加上可选属性的不确定性,导致类型不匹配。
修复方案
步骤1:给泛型T添加对象约束
确保T只能是对象类型,从根源避免基本类型引发的赋值冲突:
export default class Test<T extends object> { // ... 其余代码不变 }
步骤2:安全处理可选属性赋值
先判断block.genericObject是否存在,再用类型断言明确子集到父集的赋值合法性,避免空对象触发类型错误:
constructor(block: Test<NonFunctionProperties<T>>) { this.typedObject = { ...block.typedObject }; if (block.genericObject) { this.genericObject = block.genericObject as T; } }
完整修复后的代码
/** 获取所有非函数属性名 */ export type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]; /** 按名称挑选非函数属性 */ export type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>; /** 泛型类Test */ export default class Test<T extends object> { genericObject?: T; typedObject: object; constructor(block: Test<NonFunctionProperties<T>>) { this.typedObject = { ...block.typedObject }; if (block.genericObject) { this.genericObject = block.genericObject as T; } } } /** 使用示例 */ type CustomType = { num: number; str: string; ignoredFn: () => void; }; // 直接传入CustomType即可,构造参数会自动处理为非函数属性版本 const myTestObject = new Test<CustomType>({ genericObject: { num: 5, str: "string", }, typedObject: { num: 5, str: "string", }, });
额外优化
原使用示例中Test<NonFunctionProperties<CustomType>>可以简化为Test<CustomType>,更贴合你“传入自身无函数版本作为构造参数”的设计意图。
内容的提问来源于stack exchange,提问作者Asheh
相关产品推荐
相关产品推荐

