当结构是动态的(未知)时如何在 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 没有说明哪些字段可能返回为 null
或 undefined
,但如果是我,我会假设他们都会在那里,直到 API 给我一个证明不是这样的答复。
我正在构建一个 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 没有说明哪些字段可能返回为 null
或 undefined
,但如果是我,我会假设他们都会在那里,直到 API 给我一个证明不是这样的答复。