reactjs - TypeScript: Jag kan inte implementera en funktion med inkompatibla parametertyper


Jag har denna funktion:

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

Så, jag vill hämta tokenObj från svaret. Den är deklarerad i GoogleLoginResponse-gränssnittet men inte i GoogleLoginReponseOffline. Hur kan jag få åtkomst till denna egenskap i denna metod?

Jag skickar det som en parameter till en annan funktion som förväntar sig denna signatur. Så det är inte möjligt att ändra det.

GoogleLoginResponse-gränssnitt:

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-gränssnitt

export interface GoogleLoginResponseOffline {
  readonly code: string;
}

Hur kan jag gå vidare med detta? Jag använder https://github.com/anthonyjgrove/react-google-login-biblioteket

Redigera: Jag fixade det genom att lägga till any-typen i metoddefinitionen

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

Men jag känner mig inte bekväm med att använda typen "any" där

Svar #1

Jag stötte precis på samma problem och hittade lösningen i TypeScript-dokumentationen.

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

Du behöver skriva en extra funktion för att kontrollera typen av svaret:

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

Sedan i din onSucces-funktion kontrollera svaret så här:

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);
}

Och inga TypeScript-fel längre!

Svar #2

Du skulle kunna använda en intersectiontyp GoogleLoginResponse | GoogleLoginResponseOffline, men ärligt talat verkar det som att du troligen bara borde ha olika hanterare som kan "hantera" varje scenario separat.