Adding Typescript Declarations
Opened this issue · 6 comments
Hello, I really love geocodio, it's a great service and the node library work well.
I found it was missing a @types/geocodio-library-node module. So I made some quick type declarations for my work as I had to build it around a pre existing project.
I just wanted to leave it here for improvement and to help anybody out. It might not be exact and have some errors, I put it together rather quickly by just looking at the docs and testing the responses.
type GeocodeProps = string | Array<string>;
interface GeocodedAddress {
address_components: {
number?: string;
predirectional?: string;
street?: string;
suffix?: string;
formatted_street?: string;
secondaryunit?: string;
secondarynumber?: string;
city: string;
county?: string;
state: string;
zip: string;
country?: string;
};
formatted_address: string;
location: { lat: number; lng: number };
accuracy?: number;
accuracy_type?: string;
source?: string;
}
interface GeocodedResponse {
results: [GeocodedAddress];
}
interface GeocodedArrayResponse {
results: Array<{
query: string;
response: {
input: any;
results: [GeocodedAddress];
};
}>;
}
declare module "geocodio-library-node" {
export default class Geocodio {
constructor(apiKey: string);
geocode(
x: GeocodeProps,
y: Array<any>,
z: number
): GeocodeProps extends string
? Promise<GeocodedResponse>
: Promise<GeocodedArrayResponse>;
}
}
declare module "geocodio-library-node" {
export interface AddressParts {
country?: string;
street?: string;
city?: string;
state?: string;
postal_code?: string;
}
export type AddressMap = {
[key: string]: string;
};
export type AddressComponents = {
number?: string;
predirectional?: string;
street?: string;
suffix?: string;
formatted_street?: string;
secondaryunit?: string;
secondarynumber?: string;
city: string;
county?: string;
state: string;
zip: string;
country?: string;
};
export interface GeocodedAddress {
address_components: AddressComponents;
formatted_address: string;
location: { lat: number; lng: number };
accuracy?: number;
accuracy_type?: string;
source?: string;
fields?: { [key: string]: string };
}
export interface GeocodedResponse {
input: {
address_components: AddressComponents;
formatted_address: string;
};
results: [GeocodedAddress];
}
export interface GeocodedArrayResponse {
results: Array<{
query: string;
response: GeocodedResponse;
results: [GeocodedAddress];
}>;
}
export type AddressParam =
| string
| string[]
| AddressParts
| AddressParts[]
| AddressMap;
export type CoordinatesParam = string | string[] | [number, number];
export default class Geocodio {
constructor(apiKey?: string);
geocode(
address: AddressParam,
options?: string[],
limit?: number
): Promise<GeocodedResponse | GeocodedArrayResponse>;
reverse(
coordinates: CoordinatesParam,
options?: string[],
limit?: number
): Promise<GeocodedResponse | GeocodedArrayResponse>;
}
}
Brilliant! Haven't worked on this in a while, I just use my type defs as they satisfy what I'm working on. Good to see there's a complete list here. I'll put them in my .d.ts right now.
I reworked it slightly as I couldn't figure out how to get a Simple response to be returned from the library. Apologies about the non-usage of ternary types, couldn't figure that one out!
I've added error and _warnings to @Theauxm's types. Also my linter wants things alphabetized, so I did that too
declare module "geocodio-library-node" {
export interface AddressParts {
city?: string;
country?: string;
postal_code?: string;
state?: string;
street?: string;
}
export type AddressMap = {
[key: string]: string;
};
export type AddressComponents = {
city: string;
country?: string;
county?: string;
formatted_street?: string;
number?: string;
predirectional?: string;
secondarynumber?: string;
secondaryunit?: string;
state: string;
street?: string;
suffix?: string;
zip: string;
};
export interface GeocodedAddress {
_warnings?: string[];
accuracy?: number;
accuracy_type?: string;
address_components: AddressComponents;
fields?: { [key: string]: string };
formatted_address: string;
location: { lat: number; lng: number };
source?: string;
}
export interface GeocodedResponse {
_warnings?: string[];
input: {
address_components: AddressComponents;
formatted_address: string;
};
results: [GeocodedAddress];
}
export interface GeocodedArrayResponse {
results: Array<{
query: string;
response: GeocodedResponse;
results: [GeocodedAddress];
}>;
}
export interface GeocodedErrorResponse {
error: string;
}
export type AddressParam =
| string
| string[]
| AddressParts
| AddressParts[]
| AddressMap;
export type CoordinatesParam = string | string[] | [number, number];
export default class Geocodio {
constructor(apiKey?: string);
geocode(
address: AddressParam,
options?: string[],
limit?: number
): Promise<
GeocodedResponse | GeocodedArrayResponse | GeocodedErrorResponse
>;
reverse(
coordinates: CoordinatesParam,
options?: string[],
limit?: number
): Promise<
GeocodedResponse | GeocodedArrayResponse | GeocodedErrorResponse
>;
}
}
And some type guards
function isGeocodedError(
response: GeocodedArrayResponse | GeocodedResponse | GeocodedErrorResponse
): response is GeocodedErrorResponse {
return (response as GeocodedErrorResponse).error !== undefined;
}
function isGeocodedArrayResponse(
response: GeocodedArrayResponse | GeocodedResponse | GeocodedErrorResponse
): response is GeocodedArrayResponse {
return (response as GeocodedArrayResponse).results[0].query !== undefined;
}
Extended from @Sparticuz
- Changed
[GeocodedAddress]
toGeocodedAddress[]
because it can contain more than one result. - Added
GeocodeAccuracyType
, with different values for Forward or Reverse lookups - Added
InputAddressComponents
, since thesecondaryunit
andsecondarynumber
fields are only available on the input address.
declare module "geocodio-library-node" {
export interface AddressParts {
city?: string;
country?: string;
postal_code?: string;
state?: string;
street?: string;
}
export type AddressMap = {
[key: string]: string;
};
export interface AddressComponents {
city: string;
country?: string;
county?: string;
formatted_street?: string;
number?: string;
predirectional?: string;
state: string;
street?: string;
suffix?: string;
zip: string;
}
export interface InputAddressComponents extends AddressComponents {
secondarynumber?: string;
secondaryunit?: string;
}
export type ForwardGeocodeAccuracyType =
| "rooftop"
| "point"
| "range_interpolation"
| "nearest_rooftop_match"
| "intersection"
| "street_center"
| "place"
| "county"
| "state";
export type ReverseGeocodeAccuracyType = "rooftop" | "nearest_street" | "nearest_place";
export type GeocodeAccuracyType = ForwardGeocodeAccuracyType | ReverseGeocodeAccuracyType;
export interface GeocodedAddress<T = GeocodeAccuracyType> {
_warnings?: string[];
accuracy?: number;
accuracy_type?: T;
address_components: AddressComponents;
fields?: { [key: string]: string };
formatted_address: string;
location: { lat: number; lng: number };
source?: string;
}
export interface GeocodedResponse<T = GeocodeAccuracyType> {
_warnings?: string[];
input: {
address_components: InputAddressComponents;
formatted_address: string;
};
results: GeocodedAddress<T>[];
}
export interface GeocodedArrayResponse<T = GeocodeAccuracyType> {
results: Array<{
query: string;
response: GeocodedResponse<T>;
results: GeocodedAddress<T>[];
}>;
}
export interface GeocodedErrorResponse {
error: string;
}
export type AddressParam = string | string[] | AddressParts | AddressParts[] | AddressMap;
export type CoordinatesParam = string | string[] | [number, number];
export default class Geocodio {
constructor(apiKey?: string);
geocode(
address: AddressParam,
options?: string[],
limit?: number
): Promise<
| GeocodedResponse<ForwardGeocodeAccuracyType>
| GeocodedArrayResponse<ForwardGeocodeAccuracyType>
| GeocodedErrorResponse
>;
reverse(
coordinates: CoordinatesParam,
options?: string[],
limit?: number
): Promise<
| GeocodedResponse<ReverseGeocodeAccuracyType>
| GeocodedArrayResponse<ReverseGeocodeAccuracyType>
| GeocodedErrorResponse
>;
}
}
@Sparticuz @Theauxm @TheSecurityDev @defensadev Thanks for your collaboration on putting together the Typescript declarations. We would be happy to accept a PR to add these to the library if you'd like. Thanks!