Skip to content

Commit b3d7e92

Browse files
authored
[mod] Update incorrect type definitions with function overloading (#53)
* [mod] Update incorrect type definitions with function overloading * [mod] type definition update for What3wordsService interface * [mod] type definitions when not format provided
1 parent 009c3f5 commit b3d7e92

File tree

9 files changed

+80
-31
lines changed

9 files changed

+80
-31
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,5 @@ $RECYCLE.BIN/
210210

211211
# Snyk cacke
212212
.dccache
213+
214+
pacts/

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": false,
33
"name": "@what3words/api",
4-
"version": "4.0.6",
4+
"version": "4.0.7",
55
"description": "what3words JavaScript API",
66
"homepage": "https://github.com/what3words/w3w-node-wrapper#readme",
77
"main": "dist/index.js",

src/client/convert-to-3wa.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ApiClient } from '../lib';
22
import type { ApiClientConfiguration, Transport } from '../lib';
33
import type {
44
Coordinates,
5+
FeatureCollectionResponse,
56
LocationGeoJsonResponse,
67
LocationJsonResponse,
78
} from './response.model';
@@ -13,8 +14,9 @@ export type ConvertTo3waOptions = {
1314
};
1415

1516
export class ConvertTo3waClient extends ApiClient<
16-
LocationGeoJsonResponse | LocationJsonResponse,
17-
ConvertTo3waOptions
17+
LocationJsonResponse,
18+
ConvertTo3waOptions,
19+
FeatureCollectionResponse<LocationGeoJsonResponse>
1820
> {
1921
protected readonly method = 'get';
2022
protected readonly url = '/convert-to-3wa';

src/client/convert-to-coordinates.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ApiClient } from '../lib';
22
import type { ApiClientConfiguration, Transport } from '../lib';
33
import type {
4+
FeatureCollectionResponse,
45
LocationGeoJsonResponse,
56
LocationJsonResponse,
67
} from './response.model';
@@ -11,8 +12,9 @@ export type ConvertToCoordinatesOptions = {
1112
};
1213

1314
export class ConvertToCoordinatesClient extends ApiClient<
14-
LocationJsonResponse | LocationGeoJsonResponse,
15-
ConvertToCoordinatesOptions
15+
LocationJsonResponse,
16+
ConvertToCoordinatesOptions,
17+
FeatureCollectionResponse<LocationGeoJsonResponse>
1618
> {
1719
protected readonly method = 'get';
1820
protected readonly url = '/convert-to-coordinates';

src/client/grid-section.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ApiClient, boundsToString } from '../lib';
22
import type { ApiClientConfiguration, Transport } from '../lib';
3-
import type { Coordinates } from './response.model';
3+
import type { Coordinates, FeatureCollectionResponse } from './response.model';
44

55
export interface GridSectionJsonResponse {
66
lines: {
@@ -23,8 +23,9 @@ export type GridSectionOptions = {
2323
};
2424

2525
export class GridSectionClient extends ApiClient<
26-
GridSectionJsonResponse | GridSectionGeoJsonResponse,
27-
GridSectionOptions
26+
GridSectionJsonResponse,
27+
GridSectionOptions,
28+
FeatureCollectionResponse<GridSectionGeoJsonResponse>
2829
> {
2930
protected readonly method = 'get';
3031
protected readonly url = '/grid-section';

src/client/response.model.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,8 @@ export interface LocationGeoJsonResponse {
3636
export interface RequestOptions {
3737
[x: string]: string;
3838
}
39+
40+
export interface FeatureCollectionResponse<LocationResponse> {
41+
features: LocationResponse[];
42+
type: 'FeatureCollection';
43+
}

src/lib/client/abstract.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ import {
77
} from '../transport';
88
import { HEADERS } from '../constants';
99

10-
export abstract class ApiClient<Response, Params = undefined> {
10+
export abstract class ApiClient<
11+
JsonResponse,
12+
Params = undefined,
13+
GeoJsonResponse = JsonResponse
14+
> {
1115
protected abstract url: string;
1216
protected abstract method: 'get' | 'post';
17+
protected _config: ApiClientConfiguration;
1318
private static DEFAULT_CONFIG = {
1419
host: 'https://api.what3words.com',
1520
apiVersion: ApiVersion.Version3,
1621
};
17-
private _config: ApiClientConfiguration;
1822
private transport: Transport;
1923

2024
constructor(
@@ -44,7 +48,14 @@ export abstract class ApiClient<Response, Params = undefined> {
4448
return this._config;
4549
}
4650

47-
public async run(options?: Params): Promise<Response> {
51+
public async run(options?: Params): Promise<JsonResponse>;
52+
public async run(
53+
options?: Params & { format?: 'json' }
54+
): Promise<JsonResponse>;
55+
public async run(
56+
options?: Params & { format: 'geojson' }
57+
): Promise<GeoJsonResponse>;
58+
public async run(options?: Params): Promise<JsonResponse | GeoJsonResponse> {
4859
const validation = await this.validate(options);
4960
if (!validation.valid) {
5061
throw new Error(
@@ -57,11 +68,9 @@ export abstract class ApiClient<Response, Params = undefined> {
5768
body: this.body(options),
5869
query: this.query(options),
5970
};
60-
const response = await this.makeClientRequest<Response>(
61-
this.method,
62-
this.url,
63-
params
64-
);
71+
const response = await this.makeClientRequest<
72+
JsonResponse | GeoJsonResponse
73+
>(this.method, this.url, params);
6574
if (!response.body) throw new Error('No response body set');
6675
return response.body;
6776
}

src/service.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
AvailableLanguagesClient,
44
ConvertTo3waClient,
55
ConvertToCoordinatesClient,
6+
FeatureCollectionResponse,
67
GridSectionClient,
78
} from './client';
89
import type {
@@ -21,29 +22,43 @@ import type {
2122
import { ApiClientConfiguration } from './lib';
2223
import type { Transport } from './lib';
2324

24-
export type What3wordsService = {
25+
export interface What3wordsService {
2526
clients: {
2627
autosuggest: AutosuggestClient;
2728
availableLanguages: AvailableLanguagesClient;
2829
convertTo3wa: ConvertTo3waClient;
2930
convertToCoordinates: ConvertToCoordinatesClient;
3031
gridSection: GridSectionClient;
3132
};
32-
setApiKey: (key: string) => void;
33-
setConfig: (config: ApiClientConfiguration) => void;
34-
autosuggest: (options: AutosuggestOptions) => Promise<AutosuggestResponse>;
35-
autosuggestSelection: (options: AutosuggestSuggestion) => Promise<void>;
36-
availableLanguages: () => Promise<AvailableLanguagesResponse>;
37-
convertTo3wa: (
38-
options: ConvertTo3waOptions
39-
) => Promise<LocationGeoJsonResponse | LocationJsonResponse>;
40-
convertToCoordinates: (
33+
setApiKey(key: string): void;
34+
setConfig(config: ApiClientConfiguration): void;
35+
autosuggest(options: AutosuggestOptions): Promise<AutosuggestResponse>;
36+
autosuggestSelection(options: AutosuggestSuggestion): Promise<void>;
37+
availableLanguages(): Promise<AvailableLanguagesResponse>;
38+
convertTo3wa(options: ConvertTo3waOptions): Promise<LocationJsonResponse>;
39+
convertTo3wa(
40+
options: ConvertTo3waOptions & { format?: 'json' }
41+
): Promise<LocationJsonResponse>;
42+
convertTo3wa(
43+
options: ConvertTo3waOptions & { format: 'geojson' }
44+
): Promise<FeatureCollectionResponse<LocationGeoJsonResponse>>;
45+
convertToCoordinates(
4146
options: ConvertToCoordinatesOptions
42-
) => Promise<LocationJsonResponse | LocationGeoJsonResponse>;
43-
gridSection: (
44-
options: GridSectionOptions
45-
) => Promise<GridSectionJsonResponse | GridSectionGeoJsonResponse>;
46-
};
47+
): Promise<LocationJsonResponse>;
48+
convertToCoordinates(
49+
options: ConvertToCoordinatesOptions & { format?: 'json' }
50+
): Promise<LocationJsonResponse>;
51+
convertToCoordinates(
52+
options: ConvertToCoordinatesOptions & { format: 'geojson' }
53+
): Promise<FeatureCollectionResponse<LocationGeoJsonResponse>>;
54+
gridSection(options: GridSectionOptions): Promise<GridSectionJsonResponse>;
55+
gridSection(
56+
options: GridSectionOptions & { format?: 'json' }
57+
): Promise<GridSectionJsonResponse>;
58+
gridSection(
59+
options: GridSectionOptions & { format: 'geojson' }
60+
): Promise<FeatureCollectionResponse<GridSectionGeoJsonResponse>>;
61+
}
4762

4863
export function what3words(
4964
apiKey?: string,

test/service.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'should';
22
import nock from 'nock';
33
import { Chance } from 'chance';
4+
import { SinonSpy, spy } from 'sinon';
45
import what3words, {
56
ApiClientConfiguration,
67
ApiVersion,
78
searchParams,
89
axiosTransport,
10+
Transport,
911
} from '../src';
1012
import { What3wordsService } from '../src/service';
1113

@@ -22,6 +24,8 @@ describe('what3words', () => {
2224
let apiVersion: ApiVersion;
2325
let apiKey: string;
2426
let config: ApiClientConfiguration;
27+
let transportSpy: SinonSpy;
28+
let transport: Transport;
2529

2630
beforeEach(() => {
2731
apiKey = CHANCE.string({ length: 8 });
@@ -35,6 +39,15 @@ describe('what3words', () => {
3539
apiVersion,
3640
headers: {},
3741
};
42+
transportSpy = spy();
43+
transport = async (...args) => {
44+
transportSpy(...args);
45+
return {
46+
status: 200,
47+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
48+
body: {} as any,
49+
};
50+
};
3851
});
3952

4053
describe('Service', () => {

0 commit comments

Comments
 (0)