#typescript #apollo #react-apollo #apollo-client
#typescript #apollo #реагировать-apollo #apollo-client
Вопрос:
Я пытаюсь создать простую функцию внутри класса, который возвращает клиент Apollo. Вот мой код:
import appConfig from 'config/app-config';
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import LocalStorageKeys from 'constants/local-storage-keys';
import { setContext } from '@apollo/client/link/context';
export class ApolloClientServiceImpl {
private cache: InMemoryCache;
constructor() {
this.cache = new InMemoryCache();
}
createApolloClient(idToken: string): unknown {
const httpLink = createHttpLink({
uri: appConfig.hasura.url,
});
const authLink = setContext((_, { headers }) => {
let bearerToken = localStorage.getItem(LocalStorageKeys.TOKEN);
if (idToken) {
bearerToken = idToken;
}
return {
headers: {
...headers,
authorization: bearerToken ? `Bearer ${bearerToken}` : '',
},
};
});
return new ApolloClient({
link: authLink.concat(httpLink),
cache: this.cache,
});
}
}
Моя проблема заключается в типе возвращаемой createApolloClient
функции. Если я установлю для него значение ApolloClient<InMemoryCache>
и в инструкции return, сделайте что-то вроде этого:
return new ApolloClient<InMemoryCache>({
link: authLink.concat(httpLink),
cache: this.cache,
});
Затем я получаю следующую ошибку:
Type 'InMemoryCache' is not assignable to type 'ApolloCache<InMemoryCache>'.
Types of property 'restore' are incompatible.
Type '(data: NormalizedCacheObject) => InMemoryCache' is not assignable to type '(serializedState: InMemoryCache) => ApolloCache<InMemoryCache>'.
Types of parameters 'data' and 'serializedState' are incompatible.
Type 'InMemoryCache' is not assignable to type 'NormalizedCacheObject'.
Index signature is missing in type 'InMemoryCache'.ts(2322)
В документации клиента Apollo очень мало документации по этой теме, поэтому мой вопрос заключается в том, каков правильный возвращаемый тип этой функции?
РЕДАКТИРОВАТЬ: если я останусь только с:
return new ApolloClient({
link: authLink.concat(httpLink),
cache: this.cache,
});
И измените возвращаемый тип на ApolloClient<NormalizedCacheObject>
то, чтобы это исправило все ошибки. Спасибо Аллуану Хададу.
Комментарии:
1.
new ApolloClient<InMemoryCache>
это плохо. Должно бытьnew ApolloClient
2. @AluanHaddad оказалось, что это устранило проблему. Большое спасибо!
3. Нет проблем. Указание явных аргументов типа, особенно когда передаются значения, является антишаблоном. Правильный typescript максимально использует вывод типа
Ответ №1:
посмотрите на мой класс. Возвращаемый тип ApolloClient<NormalizedCacheObject>
import { InMemoryCache, NormalizedCacheObject } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { FragmentMatcher } from "apollo-client/core/LocalState";
import { ApolloLink } from "apollo-link";
import { onError } from "apollo-link-error";
import { HttpLink } from "apollo-link-http";
enum EApolloCLientCredentials {
DEFAULT_OMIT = "omit",
INCLUDE = "include",
SAME_ORIGIN = "same-origin",
}
class ClsApolloClient {
private _httpLink: HttpLink;
private _credentials: EApolloCLientCredentials;
private _fragmentMatcher: FragmentMatcher | undefined;
private _graphqlServerUrl: string;
private _cacheInMemoryRules: Record<string, any>;
private _apolloClient: ApolloClient<NormalizedCacheObject>;
constructor(
graphqlServerUrl: string,
credentials: EApolloCLientCredentials = EApolloCLientCredentials.DEFAULT_OMIT,
fragmentMatcher?: FragmentMatcher,
cacheInMemoryRules: Record<string, any> = {}
) {
this._graphqlServerUrl = graphqlServerUrl;
this._credentials = credentials;
this._fragmentMatcher = fragmentMatcher;
this._cacheInMemoryRules = cacheInMemoryRules;
this._apolloClient = this.initApolloClient();
}
get apolloClient(): ApolloClient<NormalizedCacheObject> {
return this._apolloClient;
}
get httpLink(): HttpLink {
return this._httpLink;
}
get cacheInMemoryRules(): Record<string, any> {
return this._cacheInMemoryRules;
}
set cacheInMemoryRules(cacheInMemoryRules: Record<string, any>) {
this._cacheInMemoryRules = cacheInMemoryRules;
this._apolloClient = this.initApolloClient();
}
get credentials(): EApolloCLientCredentials {
return this._credentials;
}
set credentials(credentials: EApolloCLientCredentials) {
this._credentials = credentials;
this._apolloClient = this.initApolloClient();
}
get fragmentMatcher(): FragmentMatcher | undefined {
return this._fragmentMatcher;
}
set fragmentMatcher(fragmentMatcher: FragmentMatcher | undefined) {
this._fragmentMatcher = fragmentMatcher;
this._apolloClient = this.initApolloClient();
}
private initApolloClient(): ApolloClient<NormalizedCacheObject> {
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
this._httpLink = new HttpLink({
uri: this._graphqlServerUrl,
credentials: this._credentials,
});
const links = [errorLink, this._httpLink];
const apolloClient: ApolloClient<NormalizedCacheObject> = new ApolloClient(
{
link: ApolloLink.from(links),
cache: new InMemoryCache({
...this._cacheInMemoryRules,
addTypename: false,
}),
fragmentMatcher: this._fragmentMatcher,
}
);
return apolloClient;
}
}
export { EApolloCLientCredentials, ClsApolloClient };