如果我从React(Typescript)中的Parent扩展Child类,为什么在Parent类中状态为只读?

拉加文德拉

我为为State定义的Parent类创建了一个接口:

interface ParentState { name: string; }

我创建了一个具有上述类型状态的组件:

class Test extends React.Component<{}, ParentState> {
  constructor(props: any) {
    super(props);

    // Works fine!
    this.state = { name: '' };
  }
}

这按预期工作。但是,如果我创建一个父级和一个子级组件,其中子级组件继承自父级,而子级状态继承自父级状态,则父级中的状态将变为只读状态。

interface ChildState extends ParentState {}

class Parent<P, S extends ParentState> extends React.Component<P, S> {
  constructor(props: P) {
    super(props);

    this.state = { name: '' };
    ^^^^^^^^^^
    // Compilation error!
    // TS2322: Type '{}' is not assignable to type 'Readonly<S>'.
  }

  render() {
    return <div>parent</div>;
  }
}

class Child extends Parent<{}, ChildState> {
  constructor(props: ChildProps) {
  super(props);

    // Works fine!
    this.state = { name: '' };
  }

  render() {
    return <div>child</div>;
  }
}

有人可以解释这种行为。

聚苯乙烯

我还有几个问题。

  1. 另外,在React库中,当我打开index.d.ts文件时,状态实际上是readonly这在前面提到的Test类中如何工作?

  2. 如果我没有在Test类的构造函数中提及props的类型,则出现编译错误,提示

    TS7006: Parameter 'props' implicitly has an 'any' type.
    

    为什么不采用{}类定义中提到的类型?

贾卡尔兹

您得到的错误类似于:

Type '{ name: string }' is not assignable to type 'Readonly<S>'.

就是说,如果您有一个type变量Readonly<S>,那么给它分配type值是不安全的{ name: string }让我们看看为什么。

由于S是通用代码,因此您编写的代码需要与将任何有效的具体类型替换为兼容S的约束SS extends ParentState,因此让我们提出一个满足该约束的类型并实例化Parent它:

interface ProblemChildState extends ParentState {
  naughtiness: true
}
const problemComponent = new Parent<{}, ProblemChildState>({});

让我们想象一下构造函数在做什么,现在S具体指定为ProblemChildState

this.state = { name: '' }; // oops!

类型this.stateReadonly<ProblemChildState>,但是如您所见,该值{ name: '' }根本无效ProblemChildState,因为它缺少该naughtiness属性。

由于该分配对混凝土无效,因此ProblemChildState该分配对泛型必须无效S因此,错误。

实际上,很难将文字值分配给泛型类型的变量。即使在极少数情况下,您可以提出一些适用于泛型类型参数的所有可能实例化的内容,编译器也可能会给您一个错误,因为这种情况太少而无法检查,因此您需要做类型断言确实,您可以通过以下声明解决此问题:

this.state = { name: '' } as Readonly<S>; // not safe!

但这出于上述原因并不安全。理想情况下,您需要更改代码,state直到您具有的具体类型时才需要进行设置S可能通过使Parentabstract类?

无论如何,希望能有所帮助。祝好运!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么Parent类的实例变量的变化会反映在Child类中?

在Typescript中,为什么需要设置定义为只读的类的属性?

为什么类中的属性不是只读的(Typescript)

如果我调用 child.listen(),为什么 Typescript 会从父类中调用重写的子方法?

PHP为什么我的全局数组在扩展类中为空

如果从另一个类中调用它,为什么我的ArrayList为空?

将在child中定义的方法设置为Parent类引用或将其添加到父对象

为什么我的类型在 React 和 TypeScript 中为 null?

为什么一个类中的这个方法没有扩展到下一个类,而是我看到 - [Function (anonymous)] in TypeScript

如果我在 parent 和 child 中 fork 和 exec 会发生什么?

在Typescript中,为库中的类创建扩展方法

为什么我在扩展jna中的Structure的类构造函数中获取NullPointerException?

在React中创建类组件时,为什么还要扩展React.Component?

为什么有状态的窗口小部件在flutter中定义为两个类?

在Java中扩展Serializable类时,我为serialVersionUID选择什么有关系吗?

为什么我不能在self是类的协议扩展中更改变量?

为什么我们要降低扩展类中某个属性的可见性?

为什么我不能将指定的初始化器放置到类的扩展中?

为什么我不能在扩展通用特征的类中调用带有参数“ this”的方法?

如果我在React useState钩子中改变状态,为什么会很重要?

什么是类在 React 中扩展 React.component

为什么在类声明中“扩展”在“实现”之前

当从扩展插件的类中调用时,为什么调用扩展活动的类不起作用?

为什么TypeScript为类生成IIFE?

为什么我不能使用 switch 语句来缩小 Typescript 中的类类型?

为什么我收到错误this.variable在Java类中为null

为什么我不能在PHP中为类变量定义连接字符串?

为什么即使我在Spring类中delcare字段,@ Autowired还是为null?

为什么我们不能在类中为方法添加默认值