当结构是动态的(未知)时如何在 Typescript 中设置类型?

How to set the type in Typescript when the structure is dynamic (not known)?

我正在构建一个 React 应用程序,我想从 https://restcountries.com/v2/ API 中获取国家/地区。 我创建了一个包含所需属性的 Country 接口。提取完成后,我希望验证提取国家的结构,这样我就可以为我的 Country 实例初始化属性。为此我创建了一个验证函数,参数是countries数组(API调用的结果)。问题是这些国家的结构是未知的,因为它来自外部来源。当然,我可以看到返回的响应的结构,但它将来可能会发生变化,因此我不想基于 API 响应的当前结构构建类型。我知道结果应该是一个数组,但我不知道数组中国家/地区对象的结构,因此我无法创建类型。参数应该是一个数组吗?我应该如何定义比 'unkown' 更好的类型?应该改为 Array 吗? 请参阅下面的验证函数:

const validateCountries = (APIResultCountries: any) => {
  const countries: Country[] = APIResultCountries.map((APIcountry: any) => {
    const {
      name,
      population,
      region,
      capital,
      flags,
      alpha2Code,
    }: {
      name: string;
      population: number;
      region: string;
      capital: string;
      flags: {
        svg: string;
        png: string;
      };
      alpha2Code: string;
    } = APIcountry;

    const country: Country = {
      name,
      population: population ?? UNKNOWN,
      region: region || UNKNOWN,
      capital: capital || UNKNOWN,
      //TODO: return template img src instead of UNKNOWN string for the flag
      flag: flags.svg || flags.png || UNKNOWN,
      code: alpha2Code,
    };

    return country;
  });
  return countries;
};

这是一个版本化的 API,因此如果响应的格式发生变化,他们也会更改版本(例如,您正在点击 API v2,但 they're now up to v3.1)。因此,您可以安全地假设响应对象的形状是固定的。

基于the example response for a v2 API call,您可以创建一个国家/地区界面,其中包含您真正关心的任何属性:

interface CountryResponse {
    name: string;
    capital: string;
    population: number;
    // etc
}

确保也 you're only asking for the fields you care about - 这将减少响应大小。

现在如果你真的想验证它们,你可以安全地假设传入类型对应于 CountryResponse -

const validateCountries = (response: CountryRespose[]): Country[] => {
    // ...
}

这里唯一需要注意的是 API 没有说明哪些字段可能返回为 nullundefined,但如果是我,我会假设他们都会在那里,直到 API 给我一个证明不是这样的答复。