6

假设我有这样的课程:

class PeopleByTag extends React.Component<RouteComponentProps<{ tag: string }>

我需要在我的构造函数中做一些事情,在这个例子中获取数据,但要做到这一点,我需要声明一个 props 参数,但如果我不指定类型,它将变成任何:

constructor(props) {
    super(props); // props is any
    this.loadData();
}

另一方面,如果我重新声明类型,代码会变得非常难看:

constructor(props: Readonly<{
    children?: React.ReactNode;
}> & Readonly<RouteComponentProps<{
    tag: string;
}, StaticContext, any>>) {
    super(props);
    this.loadData();
}

有没有办法从类扩展中自动推断道具类型,同时还可以编写构造函数?

我也不想使用已弃用的生命周期挂钩(即 ComponentWillMount)。

4

2 回答 2

2

通常constructor它本身不应该变得“非常难看”,因为类型可以单独定义,type或者interface在参数类型冗长的情况下。

props无法推断构造函数参数,因为React.Component<RouteComponentProps<{ tag: string }>>泛型参数指的是父类,React.Component而不是当前类。

从类型定义中可以看出,这为父构造函数推断出正确的类型,即super.

所以这

constructor(props) {
    super(props);
}

已验证。this.props仍然正确键入。

如果noImplicitAny使用编译器选项,则为:

constructor(props: any) {
    super(props);
}

在构造函数中使用propstyped asany可能会导致类型错误:

constructor(props: any) {
    super(props);

    props.tag; // ok
    props.nonexistentProp; // ok
}

Whilethis.props是类型安全的。

可以将一个类作为泛型进行类型化,以在构造函数中维护正确的 props 类型,但这可能被认为是矫枉过正:

export class PeopleByTag<P extends { tag: string }> extends React.Component<P> {
  constructor(props: Readonly<P>) {
    super(props); // props is any

    props.tag; // ok
    props.nonexistentProp; // not ok
    props.children; // not ok, but we rarely ever need children in constructor
  }
}

props通过为其提供不兼容的类型来防止使用 in 构造函数可能是有益的:

constructor(props: never) {
    super(props);

    props.tag; // not ok
}

如果props参数被传递给super,this.props并且props在 JavaScript 中是可互换的。它们在 TypeScript 中不可互换。this.props可以在构造函数中访问正确类型的道具。

于 2018-10-14T14:19:46.737 回答
0

正如 estus 所说,我建议定义接口或类型别名以减少重复。但是请注意,props构造函数的参数类型只能是,因为 TypeScript 编译器会根据声明Readonly<RouteComponentProps<{ tag: string }>>自动添加属性,并且您可以依赖于第二个和第三个类型参数的默认值,就像您在扩展子句。(可以说,如果构造函数的参数是真正的 props 对象,那么它的类型应该包含属性,省略属性是假的,但是省略是常见的做法,甚至出现在超级构造函数的声明中。我也省略了children@types/reactRouteComponentPropschildrenchildrenReact.ComponentReadonly在一个项目中,但似乎不再值得推荐。)此时,也许您会认为类型足够短以至于重复它是可以的,并且不值得定义接口或类型别名。

顺便说一句,这里是方法和构造函数参数类型的开放建议,默认为超类中的类型。

于 2018-10-15T05:31:26.387 回答