我有一个具有以下类型的变量:
const data: { error: string; } | { property1: string; };
(这是外部API的响应,因此我无法更改它。)
我现在想检查data
这两种可能类型中的哪一种。我试过这个:
if (typeof data.error !== 'undefined') { }
不幸的是,TypeScript然后抱怨
Property `error` does not exist on type `{ property1: string }`.
如何让TypeScript知道它是哪种类型?
答案 0 :(得分:2)
这正是TypeScript拥有user-defined type guards的原因。您可以告诉TypeScript如何区分联合的两个成员:
function dataHasError(data: { error: string; } | { property1: string; }): data is { error: string; } {
return 'error' in data;
}
然后它会在if
/ else
子句中以预期的方式缩小类型:
const data: { error: string; } | { property1: string; } = /* API response */;
if (dataHasError(data)) {
console.log(data.error); // okay
} else {
console.log(data.property1); // okay
}
如果您经常发现自己需要通过检查是否存在密钥来缩小范围,可以在库中放置以下类型保护:
function hasKey<K extends string>(obj: any, key: K): obj is Record<K, any> {
return key in obj;
}
然后可以这样写:
if (hasKey(data, 'error')) {
console.log(data.error); // okay
} else {
console.log(data.property1); // okay
}
相关说明:TypeScript有一个suggestion可以自动将key in obj
解释为类型保护,以便以下内容可以正常使用:
if ('error' in data)) {
console.log(data.error); // would be okay, currently error
} else {
console.log(data.property1); // would be okay, currently error
}
目前(从TypeScript v2.5开始)不属于该语言,因此用户定义的类型保护是目前最好的答案。
希望有所帮助;祝你好运!
答案 1 :(得分:0)
我能想到的一种简单方法是使用一种具有optional属性而不是联合类型的类型。像这样:
async void OnLoginButtonClicked(object sender)
{
try
{
....//previous code
await Task.Run( () =>
{
_navigationservice.NavigateTo(Locator.MainPageViewModel);
});
}
catch (MsalException ex)
{
//
}
}
答案 2 :(得分:0)
这是我目前正在使用的解决方法。作为一种解决方法,它很好,但我宁愿正确使用TypeScript的类型系统:
const data: any = /* API response */;
if (data.error) {
const errorData: { error: string; } = data;
// Do whatever
}
const actualData: { property1: string; } = data;