我为为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>;
}
}
有人可以解释这种行为。
聚苯乙烯
我还有几个问题。
另外,在React库中,当我打开index.d.ts文件时,状态实际上是readonly。这在前面提到的Test类中如何工作?
如果我没有在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
。的约束S
是S extends ParentState
,因此让我们提出一个满足该约束的类型并实例化Parent
它:
interface ProblemChildState extends ParentState {
naughtiness: true
}
const problemComponent = new Parent<{}, ProblemChildState>({});
让我们想象一下构造函数在做什么,现在S
具体指定为ProblemChildState
:
this.state = { name: '' }; // oops!
类型this.state
为Readonly<ProblemChildState>
,但是如您所见,该值{ name: '' }
根本无效ProblemChildState
,因为它缺少该naughtiness
属性。
由于该分配对混凝土无效,因此ProblemChildState
该分配对泛型必须无效S
。因此,错误。
实际上,很难将文字值分配给泛型类型的变量。即使在极少数情况下,您可以提出一些适用于泛型类型参数的所有可能实例化的内容,编译器也可能会给您一个错误,因为这种情况太少而无法检查,因此您需要做类型断言。确实,您可以通过以下声明解决此问题:
this.state = { name: '' } as Readonly<S>; // not safe!
但这出于上述原因并不安全。理想情况下,您需要更改代码,state
直到您具有的具体类型时才需要进行设置S
。可能通过使Parent
一abstract
类?
无论如何,希望能有所帮助。祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句