【问题标题】:Infer TypeScript type from assignment after declaration声明后从赋值推断 TypeScript 类型
【发布时间】:2019-06-29 15:55:58
【问题描述】:

为 React 组件编写测试时,通常会在 beforeEach 块中初始化组件包装器(例如 wrapper),然后在后续测试中使用它。然而,为了做到这一点,你必须在赋值之前声明 wrapper 并给它一个明确的类型,否则 TypeScript 会抱怨缺少类型。不幸的是,这种类型的计算/写出可能非常复杂。

在下面的示例中,有什么方法可以“延迟”TypeScript 抱怨下面示例中缺少wrapper 的类型,并让它从分配wrapper 的位置推断类型?

或者,是否有更好的模式来布置变量以使输入更容易?

describe('suite', () => {
  // will trigger a no implicit any error
  // but it's quite complex to manually write out the type here
  let wrapper;

  beforeEach(() => {
    const SomeElement = complexFunctionWithGenericParams(someParam);

    // ideally, we want TS to infer the type of `wrapper` from this statement
    wrapper = mountComponent(<SomeElement />);
  })

  it('does something', () => {
    expect(wrapper.state.someField).toBe(5);
  }
}

【问题讨论】:

    标签: reactjs typescript enzyme


    【解决方案1】:

    没有办法从赋值中推断出类型,因为它应该在声明时推断出来。测试中局部变量的意义在于它们可以在块之间使用,这意味着它们可以被多次赋值。即使这种推论是可能的,也是模棱两可的:

    let foo; // is the type supposed to be a number, or a string, or both, or any?
    
    it('...', () => {
      foo = 1;
    });
    
    it('...', () => {
      foo = 'foo';
    });
    

    所以应该明确指定类型,例如ReturnType:

    let wrapper: ReturnType<typeof mount>;
    

    mount 是通用的,返回类型可能不同,ReturnType 可能是 more complicated with generic functions

    由于酶shallowmount 应该使用通用参数显式指定:

    wrapper = mount<typeof SomeElement, ISomeElementProps>(<SomeElement />);
    

    直接指定泛型类型更直接,因为它知道它是什么类型 (ReactWrapper):

    let wrapper: Enzyme.ReactWrapper<ISomeElementProps, ISomeElementState, typeof SomeElement>
    

    【讨论】:

    • 理论上,TypeScript可以告诉变量只在一个地方赋值,并且只有在有一个赋值时才推断出一个类型(不是说它是否应该 i> 这样做与否哈哈)。您的回答虽然准确,但与我的发现相符。我陷入了使事情复杂化的通用功能问题;不过,您链接的答案看起来可能会有所帮助。
    • 我建议只指定类型,mount 需要以任何方式指定通用参数。我不确定这个问题是关于酶的,因为除了标签之外它并没有清楚地说明这一点,其他功能可能会有所不同。
    【解决方案2】:

    虽然不是完全不同的模式,但以下内容有助于在类似情况下消除上述警告。

    import { shallow, mount, ReactWrapper } from 'enzyme'
    
    describe('suite', () => {
      let wrapper: ReactWrapper;
    
      beforeEach(() => {
        ...
        wrapper = mount or shallow 
      })
    
      it('does something', () => {
        ...
      }
    }
    

    【讨论】:

    • 是的,同意这是解决问题的快速方法并部分解决问题!这里的缺点是 wrapper 的 props/state 不会被输入
    猜你喜欢
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 2018-10-18
    相关资源
    最近更新 更多