TypeScript 参数类型是多种类型的联合:如何确定所提供的类型并使用它?
TypeScript parameter type is a union of multiple types: How can I determine which was supplied and work with it?
我正在使用 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 属性,例如
"Property 'getBasicProfile' does not exist on type GoogleLoginResponseOffline'"
我尝试了以下方法来转换或检查参数的类型,但都给出了一种或另一种类型的错误。我的函数如下所示:
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 documentation 看起来好像 if(response instanceof GoogleLoginResponse)
很接近,在这种情况下失败,因为 GoogleLoginResponse
是一个接口,它需要是 class。
请告诉我这是怎么做到的!我看过很多标题相似的 Whosebug 问题,但 none 涵盖了这一点。
您是否尝试过使用类型断言,例如
const responseGoogleSuccess = (response: GoogleLoginResponse|GoogleLoginResponseOffline) => {
if((response as GoogleLoginResponse).googleId){
// do something with (response as GoogleLoginResponse).googleId
}
}
你需要的是一个用户定义的类型保护:https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards.
在这种情况下,您将根据 运行 时出现的对象内容检查类型,而不是根据其结构,即前面提到的接口
function isGoogleLoginResponse(response: GoogleLoginResponse|GoogleLoginResponseOffline): response is GoogleLoginResponse {
// you can check more properties here off course
return (response as GoogleLoginResponse).googleId !== undefined;
}
有了这个,您可以在 if
条件下使用该函数,然后在 if
中您可以使用响应对象,因为 GoogleLoginResponse
typescript 会理解这一点。
您可以使用 in
运算符来 narrow the type:
For a n in x
expression, where n
is a string literal or string literal type and x
is a union type, the “true” branch narrows to types which have an optional or required property n
, and the “false” branch narrows to types which have an optional or missing property n
const responseGoogleSuccess = (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
if('googleId' in response) {
const profile = response.getBasicProfile(); // response is of type GoogleLoginResponse here
}
}
您当然可以定义 custom type guard,但在这种情况下使用 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;
我正在使用 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 属性,例如
"Property 'getBasicProfile' does not exist on type GoogleLoginResponseOffline'"
我尝试了以下方法来转换或检查参数的类型,但都给出了一种或另一种类型的错误。我的函数如下所示:
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 documentation 看起来好像 if(response instanceof GoogleLoginResponse)
很接近,在这种情况下失败,因为 GoogleLoginResponse
是一个接口,它需要是 class。
请告诉我这是怎么做到的!我看过很多标题相似的 Whosebug 问题,但 none 涵盖了这一点。
您是否尝试过使用类型断言,例如
const responseGoogleSuccess = (response: GoogleLoginResponse|GoogleLoginResponseOffline) => {
if((response as GoogleLoginResponse).googleId){
// do something with (response as GoogleLoginResponse).googleId
}
}
你需要的是一个用户定义的类型保护:https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards.
在这种情况下,您将根据 运行 时出现的对象内容检查类型,而不是根据其结构,即前面提到的接口
function isGoogleLoginResponse(response: GoogleLoginResponse|GoogleLoginResponseOffline): response is GoogleLoginResponse {
// you can check more properties here off course
return (response as GoogleLoginResponse).googleId !== undefined;
}
有了这个,您可以在 if
条件下使用该函数,然后在 if
中您可以使用响应对象,因为 GoogleLoginResponse
typescript 会理解这一点。
您可以使用 in
运算符来 narrow the type:
For a
n in x
expression, wheren
is a string literal or string literal type andx
is a union type, the “true” branch narrows to types which have an optional or required propertyn
, and the “false” branch narrows to types which have an optional or missing propertyn
const responseGoogleSuccess = (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
if('googleId' in response) {
const profile = response.getBasicProfile(); // response is of type GoogleLoginResponse here
}
}
您当然可以定义 custom type guard,但在这种情况下使用 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;