TypeScript:如何让泛型定义的完整类型传递到回调函数?
解决TypeScript泛型回调中无法推断完整Props类型的问题
这个问题其实是TypeScript泛型推断优先级导致的——你当前的泛型定义让编译器优先从PropsType的约束去推断P,而不是从传入的MyObject实例反向推导它的具体props类型。不用显式指定泛型参数的话,我们可以调整泛型的定义方式,让编译器先推断出MyObject的具体类型,再从中提取props的类型。
解决方案:基于MyObject实例类型反向提取Props类型
修改doSomething函数的泛型定义,只需要接收MyObject的实例类型T,然后通过T['props']来指定回调函数的参数类型:
interface PropsType { value: number; } class MyObject<P extends PropsType> { readonly props: P; constructor(props: P) { this.props = props; } } // 修改后的doSomething函数 function doSomething<T extends MyObject<any>>( object: T, callback: (props: T['props']) => number ): number { return callback(object.props); } const myProps = { value: 21, otherValue: 42 } const myObject = new MyObject(myProps); // 现在props会被正确推断为{ value: number, otherValue: number } doSomething(myObject, (props) => props.otherValue); // 不再报错
为什么这个方法有效?
原来的泛型定义中,P和T是两个独立的泛型参数,编译器在推断时会优先尝试满足P extends PropsType的基础约束,而不会主动从T的类型中提取更具体的P。
修改后,我们让编译器先推断出T的完整类型(也就是MyObject<{ value: number, otherValue: number }>),然后通过T['props']直接引用该实例的props属性类型,这样回调函数的参数类型就会自动匹配myObject的具体props类型,不需要手动指定泛型。
另一种更严谨的写法(使用infer)
如果你想明确保留P泛型的定义,也可以用TypeScript的infer关键字从T中提取P的类型:
function doSomething<T extends MyObject<infer P>, P extends PropsType>( object: T, callback: (props: P) => number ): number { return callback(object.props); }
这种写法和第一种效果一致,只是更明确地展示了P是从T中推断出来的类型。
内容的提问来源于stack exchange,提问作者madprog
相关产品推荐
相关产品推荐

