Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add generic types to apollo client for Query and Mutation #914

Merged
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -2,6 +2,7 @@ Authors

Abhi Aiyer <abhiaiyer91@gmail.com>
Brady Whitten <bwhitten518@gmail.com>
Brett Jurgens <brett@brettjurgens.com>
Bruce Williams <brwcodes@gmail.com>
Carl Wolsey <carl@wolsey.org>
Clément Prévost <prevostclement@gmail.com>
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
Expect active development and potentially significant breaking changes in the `0.x` track. We'll try to be diligent about releasing a `1.0` version in a timely fashion (ideally within 3 to 6 months), to signal the start of a more stable API.

### vNEXT
- ApolloClient class now takes two generics, the first for Query and second for Mutation

### 0.5.4
- Fix a bug that caused apollo-client to catch errors thrown in Observer.next callbacks [PR #910](https://github.com/apollostack/apollo-client/pull/910)
Expand Down
12 changes: 6 additions & 6 deletions src/ApolloClient.ts
Expand Up @@ -233,7 +233,7 @@ export default class ApolloClient {
* a description of store reactivity.
*
*/
public watchQuery(options: DeprecatedWatchQueryOptions): ObservableQuery {
public watchQuery<T>(options: DeprecatedWatchQueryOptions): ObservableQuery<T> {
this.initStore();

if (!this.shouldForceFetch && options.forceFetch) {
Expand All @@ -255,7 +255,7 @@ export default class ApolloClient {
});
delete realOptions.fragments;

return this.queryManager.watchQuery(realOptions);
return this.queryManager.watchQuery<T>(realOptions);
};

/**
Expand All @@ -267,7 +267,7 @@ export default class ApolloClient {
* how this query should be treated e.g. whether it is a polling query, whether it should hit the
* server at all or just resolve from the cache, etc.
*/
public query(options: DeprecatedWatchQueryOptions): Promise<ApolloQueryResult> {
public query<T>(options: DeprecatedWatchQueryOptions): Promise<ApolloQueryResult<T>> {
this.initStore();

// XXX what if I pass pollInterval? Will it just keep running?
Expand All @@ -292,7 +292,7 @@ export default class ApolloClient {
});
delete realOptions.fragments;

return this.queryManager.query(realOptions);
return this.queryManager.query<T>(realOptions);
};

/**
Expand Down Expand Up @@ -326,7 +326,7 @@ export default class ApolloClient {
* for this, you can simply refetch the queries that will be affected and achieve a consistent
* store once these queries return.
*/
public mutate(options: MutationOptions): Promise<ApolloQueryResult> {
public mutate<T>(options: MutationOptions): Promise<ApolloQueryResult<T>> {
this.initStore();

// We add the fragments to the document to pass only the document around internally.
Expand All @@ -337,7 +337,7 @@ export default class ApolloClient {
});
delete realOptions.fragments;

return this.queryManager.mutate(realOptions);
return this.queryManager.mutate<T>(realOptions);
};

public subscribe(options: DeprecatedSubscriptionOptions): Observable<any> {
Expand Down
36 changes: 18 additions & 18 deletions src/core/ObservableQuery.ts
Expand Up @@ -30,8 +30,8 @@ import { addFragmentsToDocument } from '../queries/getFromAST';
import assign = require('lodash.assign');
import isEqual = require('lodash.isequal');

export type ApolloCurrentResult = {
data: any;
export type ApolloCurrentResult<T> = {
data: T | {};
loading: boolean;
networkStatus: NetworkStatus;
error?: ApolloError;
Expand All @@ -48,7 +48,7 @@ export interface UpdateQueryOptions {
variables: Object;
}

export class ObservableQuery extends Observable<ApolloQueryResult> {
export class ObservableQuery<T> extends Observable<ApolloQueryResult<T>> {
public options: WatchQueryOptions;
public queryId: string;
/**
Expand All @@ -61,10 +61,10 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
private shouldSubscribe: boolean;
private scheduler: QueryScheduler;
private queryManager: QueryManager;
private observers: Observer<ApolloQueryResult>[];
private observers: Observer<ApolloQueryResult<T>>[];
private subscriptionHandles: Subscription[];

private lastResult: ApolloQueryResult;
private lastResult: ApolloQueryResult<T>;
private lastError: ApolloError;

constructor({
Expand All @@ -80,7 +80,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
const queryId = queryManager.generateQueryId();
const isPollingQuery = !!options.pollInterval;

const subscriberFunction = (observer: Observer<ApolloQueryResult>) => {
const subscriberFunction = (observer: Observer<ApolloQueryResult<T>>) => {
return this.onSubscribe(observer);
};

Expand All @@ -97,7 +97,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
this.subscriptionHandles = [];
}

public result(): Promise<ApolloQueryResult> {
public result(): Promise<ApolloQueryResult<T>> {
return new Promise((resolve, reject) => {
const subscription = this.subscribe({
next(result) {
Expand All @@ -113,7 +113,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
});
}

public currentResult(): ApolloCurrentResult {
public currentResult(): ApolloCurrentResult<T> {
const { data, partial } = this.queryManager.getCurrentQueryResult(this, true);
const queryStoreValue = this.queryManager.getApolloState().queries[this.queryId];

Expand Down Expand Up @@ -149,7 +149,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
return { data, loading, networkStatus };
}

public refetch(variables?: any): Promise<ApolloQueryResult> {
public refetch(variables?: any): Promise<ApolloQueryResult<T>> {
this.variables = assign({}, this.variables, variables);

if (this.options.noFetch) {
Expand All @@ -172,7 +172,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {

public fetchMore(
fetchMoreOptions: FetchMoreQueryOptions & FetchMoreOptions
): Promise<ApolloQueryResult> {
): Promise<ApolloQueryResult<T>> {
return Promise.resolve()
.then(() => {
const qid = this.queryManager.generateQueryId();
Expand Down Expand Up @@ -262,7 +262,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
};
}

public setOptions(opts: ModifiableWatchQueryOptions): Promise<ApolloQueryResult> {
public setOptions(opts: ModifiableWatchQueryOptions): Promise<ApolloQueryResult<T>> {
const oldOptions = this.options;
this.options = assign({}, this.options, opts) as WatchQueryOptions;

Expand Down Expand Up @@ -291,7 +291,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
* @param variables: The new set of variables. If there are missing variables,
* the previous values of those variables will be used.
*/
public setVariables(variables: any): Promise<ApolloQueryResult> {
public setVariables(variables: any): Promise<ApolloQueryResult<T>> {
const newVariables = assign({}, this.variables, variables);

if (isEqual(newVariables, this.variables)) {
Expand Down Expand Up @@ -346,7 +346,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
this.scheduler.startPollingQuery(this.options, this.queryId, false);
}

private onSubscribe(observer: Observer<ApolloQueryResult>) {
private onSubscribe(observer: Observer<ApolloQueryResult<T>>) {
this.observers.push(observer);

// Deliver initial result
Expand Down Expand Up @@ -377,22 +377,22 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {

private setUpQuery() {
if (this.shouldSubscribe) {
this.queryManager.addObservableQuery(this.queryId, this);
this.queryManager.addObservableQuery<T>(this.queryId, this);
}

if (this.isPollingQuery) {
if (this.options.noFetch) {
throw new Error('noFetch option should not use query polling.');
}

this.scheduler.startPollingQuery(
this.scheduler.startPollingQuery<T>(
this.options,
this.queryId
);
}

const observer: Observer<ApolloQueryResult> = {
next: (result: ApolloQueryResult) => {
const observer: Observer<ApolloQueryResult<T>> = {
next: (result: ApolloQueryResult<T>) => {
this.observers.forEach((obs) => {
if (obs.next) {
obs.next(result);
Expand All @@ -414,7 +414,7 @@ export class ObservableQuery extends Observable<ApolloQueryResult> {
},
};

this.queryManager.startQuery(
this.queryManager.startQuery<T>(
this.queryId,
this.options,
this.queryManager.queryListenerForObserver(this.queryId, this.options, observer)
Expand Down