从字符串 => 类型的映射推断反应道具类型时修复打字稿警告

Posted

技术标签:

【中文标题】从字符串 => 类型的映射推断反应道具类型时修复打字稿警告【英文标题】:Fixing typescript warnings when inferring react props types from map of string=>type 【发布时间】:2021-05-02 08:04:04 【问题描述】:

我有一个名为Field 的 React 组件,它旨在呈现各种类型的表单输入,包括通过其他 React 组件实现的自定义输入。输入的类型由type 确定,它可以是已知字符串(keyof FIELD_TYPES,这反过来又确定要创建的 React 组件)或任何类型的 React 组件(基于函数或类)。这已经实现了,但是我在尝试为实现提供正确的类型时遇到了一些问题。请注意,目标之一是确保正确推断道具,以便智能感知可以建议结果元素的有效属性。

This codesandbox 展示了我正在尝试修复的 3 个不同的 Typescript 警告。每个问题都带有// FIXME 注释;

(1) & (2): Type X 不能用于索引类型 'Y' - 到目前为止,我一直无法在这里找到满足 Typescript 的方法。

(3): Typescript 不接受自定义组件 - 不确定如何修改类型以允许这样做。

我也尝试过使用区分联合,但在尝试推断作为 type 传递或通过 FIELD_TYPES 映射解决的组件的 props 时遇到了困难。使用这种方法的答案也很有效。

const FIELD_TYPES = 
  text: "input",
  checkbox: "input",
  textarea: "textarea",
  custom: Custom
 as const;
type FieldTypeMap = typeof FIELD_TYPES

type KeysOfType<T, K> =  [I in keyof T]: T[I] extends K ? I : never [keyof T]

type ReactComponentType<P = any> = React.ComponentType<P> | React.ExoticComponent<P>

type FieldTypeProps<Props = any> =
  |  type?: KeysOfType<FieldTypeMap, 'input'>  & JSX.IntrinsicElements['input']
  // FIXME(4): Is there any way to DRY this up?
  |  type: 'textarea'  & JSX.IntrinsicElements['textarea']
  |  type: 'select'  & JSX.IntrinsicElements['select']
  // FIXME(5+6): How to include props for the provided react component type?
  |  type: ReactComponentType<Props>  & Props // FIXME(5)
  |  type: KeysOfType<FieldTypeMap, ReactComponentType<Props>>  &  // FIXME(6)

提前致谢!

【问题讨论】:

我的第一反应:将custom 排除在FieldTypeMap 之外,并以不同方式处理。删除它实际上修复了一个错误“FIXME(1)”。关于“FIXME(2)”,问题在于自动类型保护在与&amp;&amp; 结合时不起作用。您必须分别检查每一件事。 我刚刚尝试通过重载为另一个问题写一些非常相似的东西,但我不能完全正确:tsplay.dev/rw2j1w 对于“FIXME(4)”:type PropsUnion = [K in keyof FieldTypeMap]: type: K &amp; JSX.IntrinsicElements[FieldTypeMap[K]] 感谢琳达的帮助,非常感谢!我会看看我是否可以做任何额外的改进,如果可以的话,我会在这个帖子中跟进。 【参考方案1】:

所以问题是您需要从固有输入类型中分离自定义组件,以便您可以映射道具。此外,由于您正在重载现有的“类型”道具,因此需要省略它。

这是现在工作的代码:https://codesandbox.io/s/typescript-inferred-react-props-forked-hrh8p?file=/src/index.tsx

【讨论】:

以上是关于从字符串 => 类型的映射推断反应道具类型时修复打字稿警告的主要内容,如果未能解决你的问题,请参考以下文章

Typescript 和 React:使用 React.Component 和条件类型化道具时类型推断失败

使用多种道具类型反应 Typescript 组件

使用 TypeScript 反应道具类型 - 如何拥有函数类型?

类型化的反应 - 道具作为 `type` 或 `interface`

反应/打字稿:参数“道具”隐含了“任何”类型错误

为什么此映射类型丢失对象文字的类型推断?