Improve typings (#813)

The ApiResponse now accepts a generics that defaults to any, same for every API method that might need a body.
This commit is contained in:
Tomas Della Vedova
2019-04-10 11:40:25 +02:00
committed by GitHub
parent 2919f93b73
commit a21281fc48
7 changed files with 371 additions and 237 deletions

View File

@ -29,10 +29,13 @@ function buildDataFrameGetDataFrameTransformStats (opts) {
* Perform a [data_frame.get_data_frame_transform_stats](https://www.elastic.co/guide/en/elasticsearch/reference/current/get-data-frame-transform-stats.html) request
*
* @param {string} transform_id - The id of the transform for which to get stats. '_all' or '*' implies all transforms
* @param {number} from - skips a number of transform stats, defaults to 0
* @param {number} size - specifies a max number of transform stats to get, defaults to 100
*/
const acceptedQuerystring = [
'from',
'size'
]
const snakeCase = {

374
api/requestParams.d.ts vendored

File diff suppressed because it is too large Load Diff

View File

@ -4352,6 +4352,12 @@ link:{ref}/get-data-frame-transform-stats.html[Reference]
|`transform_id` or `transformId`
|`string` - The id of the transform for which to get stats. '_all' or '*' implies all transforms
|`from`
|`number` - skips a number of transform stats, defaults to 0
|`size`
|`number` - specifies a max number of transform stats to get, defaults to 100
|===
=== dataFrame.previewDataFrameTransform

View File

@ -3,29 +3,101 @@
The client offers a first-class support for TypeScript, since it ships the type definitions for every exposed API.
While the client offers type definitions for Request parameters, Request bodies and responses are shipped with `any` because there is not an official spec that defines them, so we cannot make guarantees over them (but since they are shipped with `any`, you can easily override them with your own typing definitions).
NOTE: If you are using TypeScript you will be required to use _snake_case_ style to define the API parameters instead of _camelCase_.
=== How to extend the provided typings?
Extend the provided typings is very straightforward, you should declare a custom `.d.ts` file and then write inside your type extensions, following there is an example of how do it.
Other than the types for the surface API, the client offers the types for every request method, via the `RequestParams`, if you need the types for a search request for instance, you can access them via `RequestParams.Search`.
Every API that supports a body, accepts a https://www.typescriptlang.org/docs/handbook/generics.html[generics] which represents the type of the request body, if you don't configure anything, it will default to `any`.
For example:
[source,ts]
----
declare module '@elastic/elasticsearch' {
export interface ShardsResponse {
import { RequestParams } from '@elastic/elasticsearch'
interface SearchBody {
query: {
match: { foo: string }
}
}
const searchParams: RequestParams.Search<SearchBody> = {
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
// This is valid as well
const searchParams: RequestParams.Search = {
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
----
You can find the type definiton of a response in `ApiResponse`, which accepts a generics as well if you want to specify the body type, otherwise it defaults to `any`.
[source,ts]
----
interface SearchResponse<T> {
hits: {
hits: Array<{
_source: T;
}>
}
}
// Define the intefrace of the source object
interface Source {
foo: string
}
client.search(searchParams)
.then((response: ApiResponse<SearchResponse<Source>>) => console.log(response))
.catch((err: Error) => {})
----
=== A complete example
[source,ts]
----
import {
Client,
// Object that contains the type definitions of every API method
RequestParams,
// Interface of the generic API response
ApiResponse,
} from '@elastic/elasticsearch'
const client = new Client({ node: 'http://localhost:9200' })
// Define the type of the body for the Search request
interface SearchBody {
query: {
match: { foo: string }
}
}
// Complete definition of the Search response
interface ShardsResponse {
total: number;
successful: number;
failed: number;
skipped: number;
}
export interface Explanation {
interface Explanation {
value: number;
description: string;
details: Explanation[];
}
export interface SearchResponse<T> {
interface SearchResponse<T> {
took: number;
timed_out: boolean;
_scroll_id?: string;
@ -51,10 +123,26 @@ declare module '@elastic/elasticsearch' {
aggregations?: any;
}
export interface MSearchResponse<T> {
responses?: Array<SearchResponse<T>>;
// Define the intefrace of the source object
interface Source {
foo: string
}
async function run (): Promise<void> {
// Define the search parameters
const searchParams: RequestParams.Search<SearchBody> = {
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
export {};
// Craft the final type definition
const response: ApiResponse<SearchResponse<Source>> = await client.search(searchParams)
console.log(response.body)
}
run().catch(console.log)
----

4
lib/Transport.d.ts vendored
View File

@ -49,7 +49,7 @@ interface TransportOptions {
headers?: anyObject;
}
export interface RequestEvent {
export interface RequestEvent<T = any> {
body: any;
statusCode: number | null;
headers: anyObject | null;
@ -71,7 +71,7 @@ export interface RequestEvent {
// ApiResponse and RequestEvent are the same thing
// we are doing this for have more clear names
export interface ApiResponse extends RequestEvent {}
export interface ApiResponse<T = any> extends RequestEvent<T> {}
declare type anyObject = {
[key: string]: any;

View File

@ -74,10 +74,10 @@ export interface Generic {
}
const code = `
export interface ${name[0].toUpperCase() + name.slice(1)} extends Generic {
export interface ${name[0].toUpperCase() + name.slice(1)}${body ? '<T = any>' : ''} extends Generic {
${partsArr.map(genLine).join('\n ')}
${paramsArr.map(genLine).join('\n ')}
${body ? `body${body.required ? '' : '?'}: any;` : ''}
${body ? `body${body.required ? '' : '?'}: T;` : ''}
}
`

View File

@ -22,6 +22,7 @@
import {
Client,
ApiResponse,
RequestParams,
RequestEvent,
ResurrectEvent,
events,
@ -94,6 +95,40 @@ client.index({
.then((result: ApiResponse) => {})
.catch((err: Error) => {})
// --- Use generics ---
// Define the search parameters
interface SearchBody {
query: {
match: { foo: string }
}
}
const searchParams: RequestParams.Search<SearchBody> = {
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
// Dewfine the interface of the search response
interface SearchResponse<T> {
hits: {
hits: Array<{
_source: T;
}>
}
}
// Define the intefrace of the source object
interface Source {
foo: string
}
client.search(searchParams)
.then((response: ApiResponse<SearchResponse<Source>>) => console.log(response))
.catch((err: Error) => {})
// extend client
client.extend('namespace.method', (options: ClientExtendsCallbackOptions) => {
return function (params: any) {