【问题标题】:Using React forwardRef with Typescript generic JSX arguments使用带有 Typescript 通用 JSX 参数的 React forwardRef
【发布时间】:2019-01-23 20:29:08
【问题描述】:

鉴于以下使用 generic type arguments 的类型化 React 组件,我将如何将其包装在 React 的新 forwardRef API 中?

type Props<T> = {
  forwardedRef?: Ref<HTMLInputElement>
  ...
}

class GenericComponent<T> extends Component<Props<T>> {
  ...
}

const ComponentWithRef = forwardRef<HTMLInputElement, Props<T>>((props, ref) => (
  <StringInput<T> {...props} forwardedRef={ref} />
))

上述方法无法定义T泛型。

【问题讨论】:

  • 我也看不出有什么办法。您最好的选择可能是不使用forwardRef,而让调用者直接调用StringInput,传递forwardedRef 属性。请注意generic components are unsound to begin with,所以我不希望完全支持对它们的使用进行类型检查。
  • @MattMcCutchen - 是的,这是使用泛型的一个令人担忧的边缘情况:具体来说,当这些元素共享相同的底层时,一个类组件实例可以由具有不同泛型类型注释的两个不同元素支持零件。如果我理解正确的话,这个弱点只暴露在有状态的类组件中,而不是无状态的类或不跨渲染共享状态的功能组件。不过,React 处理组件生命周期的方式仍然暴露出一个有效的类型漏洞。

标签: reactjs typescript


【解决方案1】:

所以,为了扩大一些问题,这实际上是一个关于在高阶函数中保留泛型类型的问题。 forwardRef 的以下用法将正确地进行类型检查(在 3.0.1 中)

const SelectWithRef = forwardRef(<Option extends string>(props: Props<Option>, ref?: Ref<HTMLSelectElement>) =>
  <Select<Option> {...props} forwardedRef={ref} />);

但是,Option 泛型会立即解析为 string,而不是保持为泛型。因此,以下内容不会进行类型检查

const onChange: (value: 'one' | 'two') => void = (value) => console.log(value);

<SelectWithRef<'one' | 'two'>
              ^^^^^^^^^^^^^^^ [ts] Expected 0 type arguments, but got 1
  value="a"
  options={['one', 'two']}
  onChange={onChange}
           ^^^^^^^^^^ [ts] Type 'string' is not assignable to type '"one" | "two"'
/>

相关问题在this Typescript issue ticket中跟踪。

【讨论】:

    猜你喜欢
    • 2022-12-31
    • 2018-02-05
    • 2016-11-19
    • 2019-06-06
    • 2019-07-06
    • 2017-04-27
    • 2017-05-24
    • 2022-12-21
    • 2021-01-10
    相关资源
    最近更新 更多