泛型typescript函数中推断的类型参数太宽



我试图构建一个函数,接受一个函数(react component)作为参数,随后返回另一个(相关的)函数.

我想约束传入函数接受特定形状的参数(具体来说,断言存在某些道具)。

我想约束传出函数,使参数和返回类型与传入函数的"特定形状的参数"相关/推断。

这就是我想用文字表达的。在代码中,我想到的是:


function create<Props, A>(
Component: (props: Props & { callback: (a: A) => void }) => any
): (props: Props) => Promise<A> {
return null as any;
}
function MyComponent(
props: {
id: number,   // 'id' and 'name' should be inferred as 'Props'
name: string,
callback: (a: { id: number, status: string }) => void
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//   should be inferred as 'A'
}
): void { }
const myComponent = create(MyComponent)
// error on the next line: expected 'callback' to be provided
myComponent({ id: 1, name: 'abc' }).then(res => {
res.id;
//  ^? (property) id: number
res.status;
//  ^? (property) name: string
})

下面是演示错误的TS playground链接

本质上,我想确保Component有一个callback道具,我想为传出(返回)函数采取所有相同的道具作为Component,但没有回调。

我还试图推断callback的参数类型(以便它可以在返回函数的返回类型Promise<A>中使用)。


据我所知,Props基本上被推断为"包括";callback作为属性之一

如果我尝试在返回的函数中显式地使用Omit<Props, 'callback'>,我会得到错误:

'Props' could be instantiated with an arbitrary type which could be unrelated to 'Omit<Props, "callback"> & { callback: (a: A) => void; }'

下面是一个TS playground链接,演示了这个错误

我想知道是否有人能帮我弄清楚我想做的事情是否可以完成和/或我错过了什么?

我们可以断言你给Component的是正确的类型:

function create<Props, A>(
Component: (props: Props & { callback: (a: A) => void }) => any
): (props: Omit<Props, "callback">) => Promise<A> {
return (props) => new Promise(
(resolve) => Component({
...props,
callback: (a: A) => { resolve(a) }
} as Props)
);
}

但是你会注意到当我们这么做的时候,我们得到了一个错误:

类型为'Props'的参数不能赋值给类型为'Props &{callback: (a: a) =>无效;}"。类型'Props'不能赋值给类型'{callback: (a: a) =>无效;}"。(2345)输入。tsx(1,17):此类型参数可能需要extends { callback: (a: A) => void; }约束。

所以这就是为什么我添加了通用约束Props:

function create<Props extends { callback: (a: A) => void }, A>(

现在可以正常工作了

游乐场

最新更新