reactjs - NextJS Typescript - 保护后对象可能未定义?
问题描述
好吧,我被难住了。我有一个简单的 React 组件(刚开始)。我需要获取数据,所以我正在等待一些异步数据。这是我现在的解决方案:
import { Component } from "react";
import { Bible } from "./models";
interface State {
bible?: Bible;
}
export class RevApp extends Component<{}, State> {
state = {
bible: undefined,
};
componentDidMount() {
Bible.onReady().then((bible) => {
this.setState({
bible,
});
});
}
render() {
const { bible } = this.state;
//return <div>{bible ? bible.ls() : "Loading Bible..."}</div>;
if (bible) {
return <div>{bible.ls()}</div>;
} else {
return <div>Loading Bible...</div>;
}
}
}
出于某种原因,我得到了bible.ls()
(特别是圣经对象)编译器错误“对象可能未定义”。这没有任何意义!我试过放一个!(即bible!.ls()
,但后来我收到一个投诉,“'never' 类型不存在属性 'ls'”。
真正令人头疼的是,这个错误只出现在我的 linter 中,而不是我的编译器中。这一切都很好,除非当我推送到生产环境时,我的代码需要在编译之前通过 linter。
谁能告诉我为什么我会出现这种行为?
这是我的 tsconfig,以防它与问题有关(由 nextjs 生成):
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"baseUrl": "."
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
打字稿版本“4.3.5”
节点版本“14.17.3”
解决方案
无论好坏,当你有class
一个extends
超类时,子类的重写属性不会从超类继承它们的类型。相反,它们完全从初始化程序中获取类型,就好像超类不存在一样。因此,子类属性很容易成为比超类更窄的类型。请参阅microsoft/TypeScript#10570了解有关此问题的讨论,它如何使人们感到困惑,以及他们如何在这里没有找到更好的办法。
这意味着 的state
属性RevApp
不继承的类型Component<{}, State>['state']
。相反,它是从{bible: undefined}
初始化程序中推断出来的,这会导致 type {bible: undefined}
。所以bible
属性的state
属性RevApp
永远是永远undefined
:
export class RevApp extends Component<{}, State> {
state = {
bible: undefined,
};
/* RevApp.state: { bible: undefined;} <-- oops */
}
所以你不可能undefined
从类型中消除state
类型保护(嗯,你可以,也许编译器会缩小到never
,但这也不是你想要的);它保持undefined
:
const { bible } = this.state;
// const bible: undefined
if (bible) {
bible // <-- still undefined
}
想必你实际上想要state
的bible
财产也许不是undefined
。如果是这样,获得此行为的唯一方法是将其显式注释为您想要的类型:
export class RevApp extends Component<{}, State> { state: State = { // 带注释的圣经:undefined, }; }
现在类型保护按需要工作了;的类型bible
在Bible | undefined
检查之前,只要Bible
它是真实的:
render() {
const { bible } = this.state;
return <div>{bible ? bible.ls() : "Loading Bible..."}</div>; // okay
}
推荐阅读
- zend-framework3 - Zf3 使用数据库中的数据填充选择元素
- themes - Is it possible to replace Keycloak's build in account-console?
- google-sheets - 带有 if 条件的 Arrayformula - 仅隐藏行值而不包括它们
- python - 在哪里使用 Django 框架最好地执行数据库操作?
- ios - 如何在 Swift 中等待异步函数?
- conv-neural-network - 如何修复错误“无法分配给非变量...”?
- docker - nginx反向代理到其他nginx 502坏网关
- python - 何时判断我们的 CNN 模型是否过拟合?
- python - 无法在 Windows 10 中安装 Jupyter
- amazon-web-services - AWS CloudFormation 伪参数在本地不正确