TypeScript泛型疑问:如何显式指定部分泛型并推断其余?
TypeScript:部分泛型参数显式声明,其余自动推断的实现方法
问题背景
我声明了Component常量,TypeScript能按预期推断其泛型类型。但我希望扩展组件的props类型(见ComponentWithExtraProp),可一旦声明其中一个泛型参数,TypeScript就会退出类型推断并报错:"Expected 4 type arguments"。目前看来我只能选择要么显式声明所有泛型参数,要么全部让其自动推断。有没有办法只声明其中一个(或部分)泛型参数,同时让其余参数自动推断?
示例代码
export const withStaticProps = < Props, Context, StaticProps, Component extends (props: Props & StaticProps) => string, >( getStaticProps: (context: Context) => Promise<{ props: StaticProps }>, component: Component, ): Component & { getStaticProps: (context: Context) => Promise<{ props: StaticProps }>; } => { return Object.assign(component, { getStaticProps }); }; const Component = withStaticProps( async ({ bar }: { bar: string }) => Promise.resolve({ props: { foo: bar } }), (props) => `Foo: ${props.foo}`, // Foo: astring ); Component.getStaticProps({ bar: "astring" }).then((res) => { console.log(res.props.foo); // "astring" }); const ComponentWithExtraProp = withStaticProps<{ extra: string }>( // Expected 4 type arguments, but got 1. async ({ bar }: { bar: string }) => Promise.resolve({ props: { foo: bar } }), (props) => `Foo: ${props.extra}`, // Property 'extra' does not exist on type 'Props & StaticProps'. ); ComponentWithExtraProp.getStaticProps({ bar: "astring" }).then((res) => { console.log(res.props.foo); // 'res.props' is of type 'unknown'. });
解决方案
方案1:使用TypeScript 4.7+的泛型占位符_
TypeScript 4.7及以上版本支持用_作为泛型参数的占位符,代表让编译器自动推断该参数的类型。修改ComponentWithExtraProp的调用方式即可:
const ComponentWithExtraProp = withStaticProps<{ extra: string }, _, _, _>( async ({ bar }: { bar: string }) => Promise.resolve({ props: { foo: bar } }), (props) => `Foo: ${props.extra}`, );
这样既显式指定了Props类型为{ extra: string },剩余三个泛型参数由编译器自动推断,完美解决报错和类型推断失效的问题。
方案2:柯里化函数兼容低版本TypeScript
如果需要支持TypeScript 4.7以下版本,可将原函数改造成柯里化形式,先固定需要指定的泛型参数,再传入其他参数进行类型推断:
// 重构后的柯里化函数 export const withStaticProps = <Props>() => < Context, StaticProps, Component extends (props: Props & StaticProps) => string, >( getStaticProps: (context: Context) => Promise<{ props: StaticProps }>, component: Component, ): Component & { getStaticProps: (context: Context) => Promise<{ props: StaticProps }>; } => { return Object.assign(component, { getStaticProps }); }; // 使用方式 const ComponentWithExtraProp = withStaticProps<{ extra: string }>()( async ({ bar }: { bar: string }) => Promise.resolve({ props: { foo: bar } }), (props) => `Foo: ${props.extra}`, );
通过柯里化拆分调用步骤,先锁定Props类型,后续参数的泛型类型仍能被自动推断,满足部分指定的需求。
内容的提问来源于stack exchange,提问作者nomadoda
相关产品推荐
相关产品推荐

