Bruno Vasconcelos
Bruno Vasconcelos

Reputation: 179

TypeScript: I can not implement function with incompatible param types

I have this function:

function handleLoginSuccess(response: GoogleLoginResponse | GoogleLoginResponseOffline ) {
    const { access_token } = response.tokenObj;
    console.log(response.getAuthResponse());
    setIsLoggedIn(true);
  }

So, i want to get the tokenObj from the response. It is declared in the GoogleLoginResponse interface but not in the GoogleLoginReponseOffline. How can i access this property in this method?

I am passing it as a parameter of another function that expects this signature. So it is not possible to be changed.

GoogleLoginResponse Interface:

export interface GoogleLoginResponse {
  getBasicProfile(): BasicProfile;
  getAuthResponse(): AuthResponse;
  reloadAuthResponse(): Promise<AuthResponse>;
  getGrantedScopes(): string;
  getHostedDomain(): string;
  getId(): string;
  isSignedIn(): boolean;
  hasGrantedScopes(scopes: string): boolean;
  disconnect(): void;
  grantOfflineAccess(options: GrantOfflineAccessOptions): Promise<GoogleLoginResponseOffline>;
  signIn(options: SignInOptions): Promise<any>;
  grant(options: SignInOptions): Promise<any>;
  // google-login.js sez: offer renamed response keys to names that match use
  googleId: string;
  tokenObj: AuthResponse;
  tokenId: string;
  accessToken: string;
  profileObj: {
    googleId: string;
    imageUrl: string;
    email: string;
    name: string;
    givenName: string;
    familyName: string;
  }
}

GoogleLoginResponseOffline interface

export interface GoogleLoginResponseOffline {
  readonly code: string;
}

How can I proceed with this? I am using the https://github.com/anthonyjgrove/react-google-login library

Edit: I fixed it adding the any type in the method definition

function handleLoginSuccess(response: any) {
    // implementation
  }

But I am not comfortable to use the "any" type there

Upvotes: 2

Views: 293

Answers (2)

Andrew Tvorch
Andrew Tvorch

Reputation: 171

I just faced the same issue and found the solution in the TypeScript documentation.

https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

You need to write an extra function to check the type of the response:

const isGoogleLoginResponse = (response: GoogleLoginResponse | GoogleLoginResponseOffline): 
  response is GoogleLoginResponse => { 
    return !!response && 
           typeof response === 'object' && 
           !!(response as GoogleLoginResponse).tokenObj;
};

Then in your onSucces function chech the response like this:

function handleLoginSuccess(response: GoogleLoginResponse | GoogleLoginResponseOffline ) {
  if(!isGoogleLoginResponse(response)) {
    return;// Handle it however you want
  }
  const { access_token } = response.tokenObj;
  console.log(response.getAuthResponse());
  setIsLoggedIn(true);
}

And no TypeScript errors anymore!

Upvotes: 1

ehutchllew
ehutchllew

Reputation: 958

You could use an intersection type GoogleLoginResponse | GoogleLoginResponseOffline but honestly it seems like you should probably just have different handlers that can "handle" each scenario separately.

Upvotes: 0

Related Questions