TypeScript(错误:2532):尽管 null/undefined 检查,对象可能未定义
TypeScript(err:2532): object is possibly undefined dispite null/undefined check
我一直在用 TypeScript 编写一个 Discord-bot,我添加了一个从机场检索信息的命令。您唯一需要提供的是机场的 ICAO 代码(标识机场的 4 个字符代码)。现在:显然,用户可能会弄错 ICAO 代码,并可能给出无效的代码。所以这就是为什么我有一个方法从 JSON-File 中检索机场对象并且看起来有点像这样(不是精确的复制品,但只是为了让你了解它):
public getAirport(icao: string): Airport | undefined {
return arrayOfAllAirports.find(ap => ap.icao === icao);
}
在我的命令 file/class 中,我使用此方法显然可以使用给定的 ICAO 代码检索机场。然后我检查它的 return 值是否未定义,如果是,我 return *some error*
就是这样。看起来有点像这样:
let airportMgr = new AirportManager();
let airport = airportMgr.getAirport(icao);
if (airport === undefined) {
return *invalid icao error*;
}
*blablabla*
let exampleString = `ICAO: ${airport.icao} | Name: ${airport.name}`;
^error here ^error here
但是在两个 files/classes 中,我将上述方法与上述检查一起使用,我进一步得到一个错误,该对象可能未定义。现在更令人困惑的是:低几行。我再次访问 'airport' 中的一些 属性,但它什么也没说。
现在我知道我可以在检索机场或重新分配机场等时使用 as Airport
,但我想要一个合适的解决方案,而不是以愚蠢的方式欺骗打字稿。你们中有人知道如何解决这个问题吗?
编辑:
这是它工作位置的图片:https://i.stack.imgur.com/tTZyJ.png
问题是您使用的是 let
,而不是 const
。 let
可以重新分配,这意味着每次它有可能被更改时,它的类型都会被扩展到它的原始类型。像这样:
// I made it async to demonstrate something below, for your case it is not important
async function doStuff() {
// Some icao code
const icao = 'some icao';
let airport: Airport | undefined = getAirport(icao);
// Let's start by checking whether the airport is undefined
if (airport === undefined) {
return;
}
// And now let's break down all the scenarios that work
// and then all the ones that don't
//
// The important concept here is called lexical scope,
// an "environment" in which variables and constants are defined
// 1. current lexical scope - the scope of this function
//
// This should work since the value of airport has just been checked
// and has not had an opportunity to be changed
airport.name;
// 2. "child" lexical scope - scope created by a function defined within
// the current lexical scope
//
// This should not work since you might be calling this function
// some later time, when the value of airport would have possibly changed
function someHelperFunction() {
airport.name;
}
// The same applies to promise resolution values
Promise.resolve().then(() => {
// This should not work
airport.name
});
// It works with simple awaits
const anything = await Promise.resolve('something');
// This will work
airport.name;
// A TRICK (!!!)
//
// You can at this point create a const of type Airport (because now you are sure
// it is an airport) and use that in your functions.
//
// Since it is defined as const, it cannot be changed
// and it will stay an airport like forever and ever
const airportForSure: Airport = airport;
function someOtherHelperFunction() {
// WORKS!!!
airportForSure.name;
}
Promise.resolve().then(() => {
// Yesss
airportForSure.name
});
// Then when you change the value of airport, you need to check for undefined again
airport = getAirport(icao);
// This will not work
airport.name;
}
type Airport {
icao: string;
name: string;
}
// Just a placeholder for a function
declare function getAirport(icao: string): Airport | undefined;
我一直在用 TypeScript 编写一个 Discord-bot,我添加了一个从机场检索信息的命令。您唯一需要提供的是机场的 ICAO 代码(标识机场的 4 个字符代码)。现在:显然,用户可能会弄错 ICAO 代码,并可能给出无效的代码。所以这就是为什么我有一个方法从 JSON-File 中检索机场对象并且看起来有点像这样(不是精确的复制品,但只是为了让你了解它):
public getAirport(icao: string): Airport | undefined {
return arrayOfAllAirports.find(ap => ap.icao === icao);
}
在我的命令 file/class 中,我使用此方法显然可以使用给定的 ICAO 代码检索机场。然后我检查它的 return 值是否未定义,如果是,我 return *some error*
就是这样。看起来有点像这样:
let airportMgr = new AirportManager();
let airport = airportMgr.getAirport(icao);
if (airport === undefined) {
return *invalid icao error*;
}
*blablabla*
let exampleString = `ICAO: ${airport.icao} | Name: ${airport.name}`;
^error here ^error here
但是在两个 files/classes 中,我将上述方法与上述检查一起使用,我进一步得到一个错误,该对象可能未定义。现在更令人困惑的是:低几行。我再次访问 'airport' 中的一些 属性,但它什么也没说。
现在我知道我可以在检索机场或重新分配机场等时使用 as Airport
,但我想要一个合适的解决方案,而不是以愚蠢的方式欺骗打字稿。你们中有人知道如何解决这个问题吗?
编辑:
这是它工作位置的图片:https://i.stack.imgur.com/tTZyJ.png
问题是您使用的是 let
,而不是 const
。 let
可以重新分配,这意味着每次它有可能被更改时,它的类型都会被扩展到它的原始类型。像这样:
// I made it async to demonstrate something below, for your case it is not important
async function doStuff() {
// Some icao code
const icao = 'some icao';
let airport: Airport | undefined = getAirport(icao);
// Let's start by checking whether the airport is undefined
if (airport === undefined) {
return;
}
// And now let's break down all the scenarios that work
// and then all the ones that don't
//
// The important concept here is called lexical scope,
// an "environment" in which variables and constants are defined
// 1. current lexical scope - the scope of this function
//
// This should work since the value of airport has just been checked
// and has not had an opportunity to be changed
airport.name;
// 2. "child" lexical scope - scope created by a function defined within
// the current lexical scope
//
// This should not work since you might be calling this function
// some later time, when the value of airport would have possibly changed
function someHelperFunction() {
airport.name;
}
// The same applies to promise resolution values
Promise.resolve().then(() => {
// This should not work
airport.name
});
// It works with simple awaits
const anything = await Promise.resolve('something');
// This will work
airport.name;
// A TRICK (!!!)
//
// You can at this point create a const of type Airport (because now you are sure
// it is an airport) and use that in your functions.
//
// Since it is defined as const, it cannot be changed
// and it will stay an airport like forever and ever
const airportForSure: Airport = airport;
function someOtherHelperFunction() {
// WORKS!!!
airportForSure.name;
}
Promise.resolve().then(() => {
// Yesss
airportForSure.name
});
// Then when you change the value of airport, you need to check for undefined again
airport = getAirport(icao);
// This will not work
airport.name;
}
type Airport {
icao: string;
name: string;
}
// Just a placeholder for a function
declare function getAirport(icao: string): Airport | undefined;