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

Posted

技术标签:

【中文标题】类型化的反应 - 道具作为 `type` 或 `interface`【英文标题】:typed react - props as `type` or an `interface` 【发布时间】:2018-09-08 19:05:10 【问题描述】:

我有反应代码

export default class MyComponent extends Component<Props,State>

问题是,我是写像type 还是interface 这样的道具?

type Props = 
    isActive: Boolean,
    onClick: Function

interface Props 
    isActive: Boolean,
    onClick: Function

另外,当我不使用打字稿,而是使用经典的 webpack+babel 设置时,有什么区别?

或者,这对我来说很重要吗?

【问题讨论】:

【参考方案1】:

现在是 2020 年,在几乎所有使用 React 道具的情况下,我都会支持 type(一般类型与界面帖子是 here)。只能用类型别名表示的常见情况:

// given some props from another comp that are to be altered
type ExternalProps =  a: string; b:  c: number  ;

type Props_IndexType = ExternalProps["b"]; //  c: number; 
type Props_MappedType =  [K in keyof ExternalProps]: number ; //  a: number; b: number; 
type Props_DiscriminatedUnionType =  tag: "tag1"; foo: string  |  tag: "tag2"; foo: boolean
type Props_typeOf =  foo: string  & typeof defaultProps; // see class comp example

// conditional types - ok, this one is a bit contrived, but you get the point
type Props_ConditionalType<T> = T extends true ?  a: string  :  b: number ;
const Comp = <T extends >(props: Props_ConditionalType<T>) =>
  <div>"a" in props && (props as any).a</div>
render(<Comp<true> a="foo" />, document.getElementById("root"));

类组件example 用于说明(OP 提到了它们,但上述情况也适用于 Hooks):

// cannot do that with interfaces
type Props = ( tag: "tag1"; foo: string  |  tag: "tag2"; foo: boolean ) &
  typeof defaultProps;
type State = typeof initState;

const defaultProps =  a: "A" ;
const initState =  c: "C" ;

class App extends React.Component<Props, State> 
  static readonly defaultProps = defaultProps;
  state = initState;

  render()  ... 


render(<App tag="tag1" foo="foo" />, document.getElementById("root"));

唯一的情况,我会考虑接口:

您在全球范围内使用 declaration merging 的 prop 类型(现在不常见) 您想隐藏类型实现细节,因为接口会创建一个新名称,用于错误消息、IDE 类型信息等 (docs)

【讨论】:

【参考方案2】:

接口比对应的类型声明要强大一点,但是对于一组 react props 来说,这可能无关紧要。 您可以阅读有关类型和接口之间的区别in this question。

由于您不太可能扩展该界面或在其他地方扩充它,因此使用其中任何一个都可能没问题。但我想说,定义对象类型通常首选接口,因为它们更灵活。

【讨论】:

这个答案可能已经过时了。至于“更强大”的部分,也可以很容易地提出相反的观点。签出:***.com/questions/37233735/…。关于接口是否真的“更好”,网上也有更多的讨论。

以上是关于类型化的反应 - 道具作为 `type` 或 `interface`的主要内容,如果未能解决你的问题,请参考以下文章

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

道具验证中缺少反应/道具类型

将反应组件作为道具传递

在反应组件中将样式作为道具传递

收到错误的`Type'{theme:Theme; }'在尝试将其作为道具传递给App组件时无法分配给类型`

反应:作为道具的数组显示为未定义