如何扩展 React 类型以支持 html 属性作为 props?

问题描述 投票:0回答:2

给定一个采用自定义 props 和 html 属性 props 的组件,应该如何创建此类组件的界面?理想情况下,该界面还可以处理特定于 React 的 html 属性,例如使用

className
而不是
class

这是我试图找到正确接口的使用示例:

<MyComponent customProp='value' style={{textAlign: 'center'}}  />
reactjs typescript
2个回答
61
投票
interface IMyComponentProps extends React.HTMLAttributes<HTMLElement> {
  customProp: string;
}

更新: @ddek 提到了交叉点

&

我想警告您这种方法存在以下问题。


interface A {
  onClick: () => void;
}

interface B {
  onClick: (event: React.MouseEvent<HTMLElement>) => void;
}

// Typescript does not complain. This is not good
type AB = A & B;
const a: AB = {
  onClick: () => {}
};


// TS2320: Interface 'AB2' cannot simultaneously extend types 'A' and 'B'.
// Named property 'onClick' of types 'A' and 'B' are not identical.

interface AB2 extends A, B {
  
}

// TS2430: Interface 'AC' incorrectly extends interface 'A'.
//   Types of property 'onClick' are incompatible.  
//   Type '(event: MouseEvent<HTMLElement, MouseEvent>) => void' is not
// assignable to type '() => void'.
interface AC extends A {
  onClick: (event: React.MouseEvent<HTMLElement>) => void;
}

UPD 2:https://github.com/microsoft/TypeScript/wiki/Performance#preferring-interfaces-over-intersections

接口创建一个单一的平面对象类型来检测属性冲突,这通常对于解决很重要!另一方面,交集只是递归地合并属性,并且在某些情况下不会产生任何结果。界面也始终显示得更好,而交叉点的类型别名无法显示在其他交叉点的部分中。接口之间的类型关系也被缓存,而不是作为一个整体的交集类型。最后一个值得注意的区别是,在检查目标交叉点类型时,在检查“有效”/“扁平”类型之前先检查每个成分。

因此,建议使用接口/扩展来扩展类型,而不是创建交集类型。


6
投票

Yozi 是对的,但还有另一种方法,它演示了打字稿(和通用 FP)功能,如果您来自 C# 或 Java 等语言,您可能不熟悉该功能。

interface MyCustomProps {
    customProp: string;
}

const MyComponent = (props: MyCustomProps & React.HTMLAttributes<...>) 
    => (...)

在打字稿中,类型声明中的

&
指的是交集类型您可以在打字稿文档中阅读更多内容
props
对象现在结合了
MyCustomProps
的属性和 HTML 属性。 (还值得学习受歧视的联合或
or
类型,它们用
|
表示。我发现它们比交集更有用)。

如果你想清理你的方法签名,你可以声明类型如下:

interface MyCustomProps {...}
type ComponentProps = MyCustomProps & React.HTMLAtributes<...>;

但是,这种表示法现在失去了之前两种方法的简洁性 -

extends
语法和
&
表示法。

© www.soinside.com 2019 - 2024. All rights reserved.