【问题标题】:Why does Typescript with strictNullChecks enabled ignores null checks on React's state?为什么启用了 strictNullChecks 的 Typescript 会忽略对 React 状态的空检查?
【发布时间】:2019-10-03 18:05:41
【问题描述】:

在下面的例子中:

interface AppState {
    text: string | null;
}

interface ChildProps {
    text: string;
}

class App extends React.Component<{}, AppState> {
    state = {
        text: null
    };
    componentDidMount() {
        setTimeout(() => {
            this.setState({ text: "rendered!" });
        }, 5000);
    }
    render() {
        return this.state.text !== null ? (
            <Child text={this.state.text} />
        ) : (
            "loading..."
        );
    }
}

class Child extends React.Component<ChildProps> {
    render() {
        const { text } = this.props;
        return <div>{text}</div>;
    }
}

&lt;Child text={this.state.text} /&gt;下出现错误:

类型 'null' 不可分配给类型 'string'.ts(2322)

这没有意义,因为在渲染之前有一个明确的空检查。

为什么从状态中提取text时,错误消失了?

render() {
        const { text } = this.state;
        return text !== null ? (
            <Child text={text} />
        ) : (
            "loading..."
        );
    }

启用错误的工作示例,替换代码以查看它已修复:

https://codesandbox.io/s/react-typescript-playground-g15mw

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    如果将 state 初始化为类属性,则需要声明其类型定义。否则 typescript 假定你覆盖了它继承自 React.Component&lt;{}, AppState&gt; 的类型,它的类型变成了 { text: null }

    class App extends React.Component<{}, AppState> {
        state: AppsState = {
            text: null
        };
    }
    

    或者只是在构造函数中初始化状态

    class App extends React.Component<{}, AppState> {
        constructor(props: {}) {
            super(props)
    
            this.state = {
                text: null
            }
        }
    }
    

    至于提取

    // typeof this.state === { test: null }
    const { text } = this.state;
    
    if (this.state.text !== null) {
        // typeof this.state.text is still null
    }
    
    if (text !== null) {
        // typeof text is never here
        // since never is subtype of all types
        // text can be assigned to any variable
    }
    

    https://www.typescriptlang.org/docs/handbook/basic-types.html#never查看更多信息

    【讨论】:

    • 非常感谢!似乎它属于不可能类型的上下文:因为文本只能在 state 被推断为 {text: null} 时为空,并且我们显式传递了一个在它不是时发生的条件 - 它会自动将其转换为 never。更多信息:mariusschulz.com/blog/… 唯一的问题是,为什么 TS 允许在类属性时扩展类型?您仍然需要启动text,但是您可以随时添加更多密钥。
    猜你喜欢
    • 2021-12-20
    • 2022-08-15
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 2015-01-13
    • 2021-11-04
    • 2017-01-16
    • 1970-01-01
    相关资源
    最近更新 更多