reactjs - TypeScript 参数类型是多种类型的联合:如何确定提供了哪些类型并使用它?
问题描述
我正在使用 TypeScript 中的React Google Login库。它具有 TypeScript 的类型绑定,但所有示例都使用 JavaScript,而且我对 TypeScript 还是很陌生。
设置代码如下所示:
<GoogleLogin
clientId="client-id-value"
onSuccess={successResponseGoogle}
onFailure={failureResponseGoogle}
cookiePolicy={'single_host_origin'}
/>
在 TypeScript 中,onSuccess 回调的签名是:
readonly onSuccess: (response: GoogleLoginResponse | GoogleLoginResponseOffline) => void
该GoogleLoginResponseOffline
类型只有一个属性 ,code
其中GoogleLoginResponse
有一系列属性可以访问经过身份验证的用户的详细信息。
我遇到的问题是 TypeScript 不允许我访问响应参数上的任何 GoogleLoginResponse 属性,例如
“类型 GoogleLoginResponseOffline 上不存在属性 'getBasicProfile'”
我尝试了以下方法来强制转换或检查参数的类型,但都给出了一种或另一种类型的错误。我的功能如下所示:
const responseGoogleSuccess = (response: GoogleLoginResponse|GoogleLoginResponseOffline) => {
// Tried to check for property to identify type
if(response.googleId){ // Property 'googleId' does not exist on type 'GoogleLoginResponseOffline'
const profile = response.getBasicProfile(); // Property 'getBasicProfile' does not exist on type 'GoogleLoginResponseOffline'
}
// Tried to cast like this
const typedResponse = <GoogleLoginResponse>response;
// Tried to check type
if(response instanceof GoogleLoginResponse){ // 'GoogleLoginResponse' only refers to a type, but is being used as a value here.
}
}
它从TypeScript 文档中看起来好像if(response instanceof GoogleLoginResponse)
很接近,在这种情况下失败,因为GoogleLoginResponse
它是一个接口并且它需要是一个类。
请告诉我这是怎么做到的!我查看了很多标题相似的 StackOverflow 问题,但没有一个涵盖这一点。
解决方案
您可以使用in
运算符来缩小类型:
对于
n in x
表达式,其中n
是字符串文字或字符串文字类型并且x
是联合类型,“真”分支缩小到具有可选或必需属性的类型n
,而“假”分支缩小到具有可选或缺失属性的类型财产n
const responseGoogleSuccess = (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
if('googleId' in response) {
const profile = response.getBasicProfile(); // response is of type GoogleLoginResponse here
}
}
您当然可以定义自定义类型保护,但在这种情况下使用in
运算符要容易得多。但是如果你在几个地方需要这个,可以这样定义类型保护:
type Reposense = GoogleLoginResponse | GoogleLoginResponseOffline;
const responseGoogleSuccess = (response: Reposense) => {
if (isLoginResponse(response)) {
const profile = response.getBasicProfile();
}
}
const isLoginResponse = (response: Reposense): response is GoogleLoginResponse =>
'googleId' in response;
推荐阅读
- android - Android回调和监听器的区别
- javascript - 从先前的组件渲染中预先填充的 React useState
- javascript - 查找小于或等于一个数字的所有斐波那契数
- c# - 关于 acumatica,有没有办法从一个表中获取一个变量并将其用作另一个表的 id 的一部分?
- reactjs - Django urls.py + React 路由器
- jestjs - 来自另一个函数的 fn() 模拟警报
- python - 有没有办法增加 tinydb JSON 限制?
- php - Symfony / Doctrine - 资源竞赛
- java - 执行我的 java apache poi 程序后无法打开 Excel 文件,我正在使用文件输出流
- php - PHP按域名排序数据库