空脚本{}在打字稿中的类型不是{}

时间:2019-05-22 07:13:28

标签: typescript

我有以下帮助方法,该方法返回一个包装好的react组件。

export function wrapComponentInContext<T extends object = {}>(
  Comp: React.FunctionComponent<T>, 
  props: T = {}) { // ERROR: Type '{}' is not assignable to type 'T'

  const mockSetter = jest.fn(() => { });    
  const mockContext: ContextDefaultValue = ["context", mockSetter];

  return (
    <Provider value={mockContext}>
      <Comp {...props}/>
    </Provider>
  );
}

如果不提供任何参数,我想默认为空对象。

这是一个更简单的example

所以看来一个空对象不是{}类型,这很令人困惑。

为什么

1 个答案:

答案 0 :(得分:1)

通用函数必须对传递给该函数的任何可能的T有效。 T extends object表示T可以是任何对象类型,因此它可以是{ foo: string },而{}对此类型不是有效的默认值。

type参数的默认类型与该参数的默认值没有任何关系。您可以使用显式类型参数且不使用默认值进行调用,从而在传入的默认值{}T之间产生冲突。或者您可以省略默认值,并传入具有必需道具的组件:

declare function comp(o: { p: string }): void;
wrapComponentInContext(comp)

您可以使用类型断言来强制{}进入T

export function wrapComponentInContext<T extends object = {}>(Comp: React.FunctionComponent<T>, props: T = {} as T) {

}

但是,这将使您暴露于上面我强调的潜在问题。您可以为{}是有效默认值的组件添加专用的重载,尽管由于函数参数的相反性质,使其按预期工作需要一些条件类型:

declare function compOptional(o: { p?: string }): void;
declare function comp(o: { p: string }): void;

export function wrapComponentInContext<T>(Comp: React.FunctionComponent<T> & ({} extends T ? {} : "Provide default props as component requires some"))
export function wrapComponentInContext<T extends object>(Comp: React.FunctionComponent<T>, props: T)
export function wrapComponentInContext<T extends object = {}>(Comp: React.FunctionComponent<T>, props: T = {} as T) {

}
wrapComponentInContext(comp) // Type '(o: { p: string; }) => void' is not assignable to type '"Provide default props as component requires some"'.
wrapComponentInContext(compOptional)
wrapComponentInContext(comp, { p: "" })