Eri*_*ric 6 typescript reactjs
将组件的状态初始化为组件null构造函数外部时,状态never在render函数中具有类型.
但是,在构造函数中初始化状态时,状态具有正确的类型.
根据StackOverflow上关于初始化状态的两种方法(在babeled JS中)的大多数问题,这两种方法应该是等价的.但是,在Typescript中,它们不是.这是一个错误还是预期的行为?
import * as React from "react";
import * as ReactDOM from "react-dom";
interface Person {
name: string;
address: string;
}
interface Props {
items: Person[];
}
interface State {
selected: Person | null;
}
class PersonSelector extends React.Component<Props, State> {
// DOES NOT WORK:
state = {
selected: null
};
constructor(props: Props) {
super(props);
// WORKS:
// this.state = {
// selected: null
// };
}
handleClick = (item: Person) => {
this.setState({
selected: item
});
};
render() {
const { selected } = this.state;
let selectedLabel = <div>None selected</div>;
if (selected) {
selectedLabel = <div>You selected {selected.name}</div>;
}
return (
<div>
{selectedLabel}
<hr />
{this.props.items.map(item => (
<div onClick={() => this.handleClick(item)}>{item.name}</div>
))}
</div>
);
}
}
const people: Person[] = [
{ name: "asdf", address: "asdf asdf" },
{ name: "asdf2", address: "asdf asdf2" }
];
document.write('<div id="root"></div>');
ReactDOM.render(
<PersonSelector items={people} />,
document.getElementById("root")
);
Run Code Online (Sandbox Code Playgroud)
以下是CodeSandbox上的示例代码:https://codesandbox.io/s/10l73o4o9q
art*_*tem 11
根据StackOverflow上关于初始化状态的两种方法(在babeled JS中)的大多数问题,这两种方法应该是等价的.但是,在Typescript中,它们不是.
他们是打字稿不同,因为分配state在类主体(未在构造函数中)声明state中PersonSelector,覆盖在基类中声明React.Component.在TypeScript中,允许覆盖声明具有不同的,更严格的类型,与基类中相同属性的类型单向兼容.
初始化时没有类型注释,此类型由值的类型确定:
class PersonSelector extends React.Component<Props, State> {
// DOES NOT WORK:
state = {
selected: null
};
Run Code Online (Sandbox Code Playgroud)
你可以看到该类型的stateIS {selected: null},符合市场预期.它变成never了这段代码
const { selected } = this.state;
let selectedLabel = <div>None selected</div>;
if (selected) {
Run Code Online (Sandbox Code Playgroud)
因为内if声明的类型,selected变窄,使用的信息selected是true.Null永远不会是真的,因此类型变为never.
如其他答案所示,您可以State在类体初始化时明确注释
class PersonSelector extends React.Component<Props, State> {
state: State = {
selected: null
};
Run Code Online (Sandbox Code Playgroud)
更新以阐明类主体中的初始化与构造函数中的赋值不同
state在构造函数中设置时
constructor(props: Props) {
super(props);
this.state = {
selected: null
};
}
Run Code Online (Sandbox Code Playgroud)
您将值分配给state已在基类中声明的属性.基类是React.Component<Props, State>,并且state声明具有State类型的属性取自第二个泛型参数<Props, State>.
分配不会更改属性的类型 - State无论分配的值如何,它都会保留.
当您state在类体中设置时,它不仅仅是赋值 - 它是类属性的声明,并且每个声明都为声明的实体提供一种类型 - 显式地通过类型注释,或者从初始值隐式推断.即使属性已存在于基类中,也会发生此类型的输入.我在文档中找不到任何确认这一点的内容,但是有github问题确切描述了这种行为,并确认有时它违背了开发人员的意图(到目前为止还没有用该语言实现的解决方案).
您绝对可以在构造函数之外初始化状态,但是您需要确保键入它,以便 TypeScript 可以协调初始值的类型和泛型的类型。尝试:
class PersonSelector extends React.Component<Props, State> {
state: State = {
selected: null
};
// ...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2557 次 |
| 最近记录: |