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,而不是 constlet 可以重新分配,这意味着每次它有可能被更改时,它的类型都会被扩展到它的原始类型。像这样:

// 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;

Link to TypeScript playground