在 TypeScript 的 React 应用中使用 PropTypes
PropTypes在TypeScript React应用程序中的使用是非常常见的,它用于定义组件的属性类型。然而,在使用PropTypes生成TypeScript类型时可能会出现一些问题。
在上面的代码示例中,我们可以看到如何从PropTypes生成TypeScript类型。首先,我们定义了一个propTypes对象,其中包含了input属性的类型定义。然后,我们使用PropTypes.InferProps来生成MyComponentProps类型,它会自动推断出propTypes对象中的属性类型。最后,我们将MyComponentProps作为泛型参数传递给FunctionComponent,并将其作为组件的属性类型。
这种方法看起来非常不错,但是可能会有一些问题。首先,PropTypes是在运行时进行类型检查的,而TypeScript是在编译时进行类型检查的。因此,如果PropTypes中定义的类型与实际使用的类型不一致,可能会导致运行时错误。此外,由于PropTypes是通过注释来定义的,因此可能存在一些遗漏或错误的情况。
另外,PropTypes只能提供属性类型的定义,而不能提供属性名称或默认值的定义。这可能会导致在使用属性时出现一些困惑或错误。
为了解决这些问题,我们可以考虑使用TypeScript的原生类型系统来定义属性类型。这样可以在编译时进行类型检查,并且可以提供更准确和完整的类型定义。下面是一个使用TypeScript类型定义属性的示例:
interface MyComponentProps { input: { id: number; name: string; }; } const MyComponent: FunctionComponent= (props) => { // ... } export default MyComponent;
在这个示例中,我们使用interface关键字定义了MyComponentProps类型,其中包含了input属性的类型定义。然后,我们将MyComponentProps作为泛型参数传递给FunctionComponent,并使用它作为组件的属性类型。这样可以确保属性类型的准确性,并且在编译时就能发现潜在的错误。
总结起来,虽然可以使用PropTypes生成TypeScript类型,但是它可能会导致一些运行时错误和不完整的类型定义。相比之下,使用TypeScript的原生类型系统来定义属性类型可以提供更好的类型安全性和完整性。因此,建议在TypeScript React应用程序中优先使用TypeScript的原生类型系统来定义属性类型。
在使用TypeScript编写React应用程序时,有时会同时维护组件属性作为TypeScript类型和React.PropTypes。这种情况通常没有太多价值,但以下情况下同时使用这两种方式是有用的:
1. 发布一个包(例如组件库),将被纯JavaScript使用。
2. 接受和传递外部输入,例如来自API调用的结果。
3. 使用可能没有充足或准确类型定义的库中的数据。
因此,通常是一个关于可以信任编译时验证的程度的问题。较新版本的TypeScript现在可以基于React.PropTypes推断类型(PropTypes.InferProps),但生成的类型在代码的其他地方可能难以使用或引用。
如果你正在编写一个将被不使用TypeScript的开发人员安装的包,他们仍然需要PropTypes以便在运行时获得错误。如果你的项目只针对自己或其他TypeScript项目,那么你的props的TypeScript接口就足够了,因为该项目根本不会构建。
如果你想要一个oneOfType,即可选的联合类型,TypeScript具有联合类型,但它们不完全提供相同的功能。
有一些工具可以解决这个问题。例如,有一个名为ts-react-loader的工具,可以在Webpack级别上从TypeScript接口添加PropTypes。还有一个名为ts-proptypes-transformer的库,它作为TypeScript编译器转换器实现,可以为深层泛型、联合类型等生成准确的PropTypes。当然,这些工具可能还存在一些问题,希望能够得到贡献和改进。
有人希望能够避免在每个组件中重复定义PropTypes,希望有一种更好的方式只定义一次以适用于PropTypes和类型定义。
需要注意的是,仅仅因为代码可以编译通过,并不意味着它与PropTypes完全相同。我们仍然可以选择性地将字符串传递给某个属性并传递null,但isRequired将在运行时标记为未设置。
因此,这是一个关于可以或愿意信任编译时验证程度的问题。我已经列出了对运行时验证最有用的情况。这是一个权衡的问题。
在一个TypeScript的React应用中,为什么会出现PropTypes的问题以及解决方法?
TypeScript和PropTypes有不同的用途。TypeScript在编译时验证类型,而PropTypes在运行时检查。TypeScript在编写代码时非常有用:如果将错误类型的参数传递给React组件,它会发出警告,并为函数调用提供自动完成等功能。
PropTypes在测试组件与外部数据交互时很有用,例如从API加载JSON数据。PropTypes将通过打印有用的消息来帮助您调试(在React的开发模式下),以解决组件失败的原因,例如:
Warning: Failed prop type: Invalid prop `id` of type `number` supplied to `Table`, expected `string`
尽管TypeScript和PropTypes似乎执行相同的功能,但它们实际上没有重叠。但是可以从TypeScript自动生成PropTypes,以避免重复指定类型,例如:
- https://github.com/milesj/babel-plugin-typescript-to-proptypes
- https://github.com/grncdr/ts-react-loader#what-it-does
- https://github.com/gcanti/prop-types-ts
propTypes和TypeScript类型容易不同步吗?有没有人有维护经验来告诉我们?
这是正确的答案!PropTypes(运行时)和静态类型检查(编译时)并不相同。因此,使用两者并非是一个“无意义的练习”。
这里有一个很好的解释,说明如何从PropTypes推断出静态类型:https://dev.to/busypeoples/notes-on-typescript-inferring-react-proptypes-1g88
当您使用vue cli进行热重新加载和eslint时,运行时和编译时没有意义。这将在保存时生成错误。热重新加载与运行时没有任何共同之处。即使使用热重新加载,您也无法知道API实际返回什么。
如何为函数(hooks)生成propTypes?ts-loader插件似乎不支持函数组件,而babel插件则需要设置babel,我希望避免这样做。
“TypeScript和PropTypes有不同的用途。TypeScript在编译时验证类型,而PropTypes在运行时检查。”---编译时和运行时不是不同的“目的”。它们是同一个目的的不同方式,而编译时是更优的方式。