{"id":29884774,"url":"https://github.com/vahor/typed-es","last_synced_at":"2026-04-08T12:05:22.440Z","repository":{"id":306753585,"uuid":"1026738728","full_name":"Vahor/typed-es","owner":"Vahor","description":"Automatically add output types to your Elasticsearch queries.","archived":false,"fork":false,"pushed_at":"2026-03-25T09:51:06.000Z","size":521,"stargazers_count":1,"open_issues_count":26,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T12:58:23.097Z","etag":null,"topics":["aggregation","elasticsearch","hacktoberfest","query","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Vahor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["vahor"]}},"created_at":"2025-07-26T14:07:51.000Z","updated_at":"2026-03-25T09:49:45.000Z","dependencies_parsed_at":"2025-07-27T12:42:47.288Z","dependency_job_id":"764b3dc6-3b56-4ebb-8d48-44b56c4a22b6","html_url":"https://github.com/Vahor/typed-es","commit_stats":null,"previous_names":["vahor/typed-es"],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/Vahor/typed-es","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vahor%2Ftyped-es","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vahor%2Ftyped-es/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vahor%2Ftyped-es/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vahor%2Ftyped-es/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Vahor","download_url":"https://codeload.github.com/Vahor/typed-es/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vahor%2Ftyped-es/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31307069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aggregation","elasticsearch","hacktoberfest","query","typescript"],"created_at":"2025-07-31T15:08:13.265Z","updated_at":"2026-04-02T13:27:14.268Z","avatar_url":"https://github.com/Vahor.png","language":"TypeScript","funding_links":["https://github.com/sponsors/vahor"],"categories":[],"sub_categories":[],"readme":"# Typed ES\n\n[![Code quality](https://github.com/vahor/typed-es/actions/workflows/quality.yml/badge.svg)](https://github.com/vahor/typed-es/actions/workflows/quality.yml)\n[![npm downloads](https://img.shields.io/npm/dm/%40vahor%2Ftyped-es)](https://www.npmjs.com/package/@vahor/typed-es)\n\n\nAutomatically add output types to your Elasticsearch queries.\n\nTested with Elasticsearch `8` and `9`.\n\n\u003cdetails\u003e\n\u003csummary\u003eSupported Aggregations\u003c/summary\u003e\n\n### Bucket Aggregations\n| Aggregation | Status | Documentation |\n|-------------|--------|---------------|\n| Adjacency Matrix | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-adjacency-matrix-aggregation) |\n| Auto Date Histogram | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-autodatehistogram-aggregation) |\n| Categorize Text | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-categorize-text-aggregation) |\n| Children | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-children-aggregation) |\n| Composite | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-composite-aggregation) |\n| Date Histogram | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-datehistogram-aggregation) |\n| Date Range | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-daterange-aggregation) |\n| Diversified Sampler | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-diversified-sampler-aggregation) |\n| Filter | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-filter-aggregation) |\n| Filters | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-filters-aggregation) |\n| Frequent Item Sets | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-frequent-item-sets-aggregation) |\n| Geohash Grid | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation) |\n| Geohex Grid | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation) |\n| Geotile Grid | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation) |\n| Global | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-global-aggregation) |\n| Histogram | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-histogram-aggregation) |\n| IP Prefix | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-ipprefix-aggregation) |\n| IP Range | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-iprange-aggregation) |\n| Missing | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-missing-aggregation) |\n| Multi Terms | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-multi-terms-aggregation) |\n| Parent | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-parent-aggregation) |\n| Nested | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-nested-aggregation) |\n| Random Sampler | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-random-sampler-aggregation) |\n| Range | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-range-aggregation) |\n| Rare Terms | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-rare-terms-aggregation) |\n| Reverse Nested | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-reverse-nested-aggregation) |\n| Sampler | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-sampler-aggregation) |\n| Significant Terms | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-significantterms-aggregation) |\n| Significant Text | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-significanttext-aggregation) |\n| Terms | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-terms-aggregation) |\n| Time Series | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-time-series-aggregation) |\n| Variable Width Histogram | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-variablewidthhistogram-aggregation) |\n\n### Metrics Aggregations\n| Aggregation | Status | Documentation |\n|-------------|--------|---------------|\n| Avg | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-avg-aggregation) |\n| Boxplot | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-boxplot-aggregation) |\n| Cardinality | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-cardinality-aggregation) |\n| Cartesian Bounds | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-cartesian-bounds-aggregation) |\n| Cartesian Centroid | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-cartesian-centroid-aggregation) |\n| Extended Stats | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-extendedstats-aggregation) |\n| Geo Bounds | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-geobounds-aggregation) |\n| Geo Centroid | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-geocentroid-aggregation) |\n| Geo Line | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-geo-line) |\n| Matrix Stats | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-matrix-stats-aggregation) |\n| Max | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-max-aggregation) |\n| Median Absolute Deviation | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-median-absolute-deviation-aggregation) |\n| Min | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-min-aggregation) |\n| Percentile Ranks | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-percentile-rank-aggregation) |\n| Percentiles | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-percentile-aggregation) |\n| Rate | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-rate-aggregation) |\n| Scripted Metric | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-scripted-metric-aggregation) |\n| Stats | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-stats-aggregation) |\n| String Stats | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-string-stats-aggregation) |\n| Sum | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-sum-aggregation) |\n| T-Test | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-ttest-aggregation) |\n| Top Hits | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-top-hits-aggregation) |\n| Top Metrics | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-top-metrics) |\n| Value Count | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-valuecount-aggregation) |\n| Weighted Avg | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-weight-avg-aggregation) |\n\n### Pipeline Aggregations\n| Aggregation | Status | Documentation |\n|-------------|--------|---------------|\n| Average Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-avg-bucket-aggregation) |\n| Bucket Script | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-bucket-script-aggregation) |\n| Bucket Count K-S Test | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-count-ks-test-aggregation) |\n| Bucket Correlation | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-correlation-aggregation) |\n| Bucket Selector | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-bucket-selector-aggregation) |\n| Bucket Sort | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-bucket-sort-aggregation) |\n| Change Point | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-change-point-aggregation) |\n| Cumulative Cardinality | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-cumulative-cardinality-aggregation) |\n| Cumulative Sum | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-cumulative-sum-aggregation) |\n| Derivative | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-derivative-aggregation) |\n| Extended Stats Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-extended-stats-bucket-aggregation) |\n| Inference | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-inference-bucket-aggregation) |\n| Max Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-max-bucket-aggregation) |\n| Min Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-min-bucket-aggregation) |\n| Moving Function | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-movfn-aggregation) |\n| Moving Percentiles | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-moving-percentiles-aggregation) |\n| Normalize | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-normalize-aggregation) |\n| Percentiles Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-percentiles-bucket-aggregation) |\n| Serial Differencing | ❌ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-serialdiff-aggregation) |\n| Stats Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-stats-bucket-aggregation) |\n| Sum Bucket | ✅ | [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-pipeline-sum-bucket-aggregation) |\n\n\u003c/details\u003e\n\n## Features\n- **Automatic type based on options**: Automatically infers output types from query options (e.g., returning `total` count).  \n- **Automatic output type based on requested fields and aggregations**: Derives precise types from specified `_source`, `fields`, `docvalue_fields` and `aggregations` configurations.  \n- **Understand wildcards**: The library correctly detects and infers output types even when using wildcards in `_source`.  \n  For example, given an index with fields `{ created_at: string; title: string }`,  \n  specifying `_source: [\"*_at\"]` will correctly return `{ created_at: string }` in the output type.  \n- **Supports `search`, [`msearch`](#usage-with-msearch) and [`asyncSearch`](#usage-with-asyncsearch)**: You can still use the native types if something goes wrong (see [What if the library is missing a feature that you need?](#what-if-the-library-is-missing-a-feature-that-you-need)).\n\n## Example Usage\n```ts\ntype MyIndex = {\n   \"my-index\": {\n      id: number;\n      name: string;\n      created_at: string;\n   }\n};\n\n// Having to use `as unknown` is less than ideal, but as we're overriding types, typescript isn't very happy\nconst client = new Client({/* config */}) as unknown as TypedClient\u003cIndexes\u003e;\n\n// Query with _source (wildcard), fields, aggregation, and options\nconst query = typedEs(client, {\n\tindex: \"my-index\",\n\t_source: [\"id\", \"na*\"],\n\tfields: [\n\t\t{\n\t\t\tfield: \"created_at\",\n\t\t\tformat: \"yyyy-MM-dd\",\n\t\t},\n\t],\n\ttrack_total_hits: true,\n\trest_total_hits_as_int: true, // Ensures total value is returned as a number\n\taggs: {\n\t\tname_counts: { terms: { field: \"name\" } },\n\t},\n});\n\nconst result = await client.search(query);\nconst total = result.hits.total; // number\nconst firstHit = result.hits.hits[0]; // { _source: { id: number; name: string}, fields: { created_at: string[] } }\nconst aggregationBuckets = result.aggregations.name_counts.buckets; // Array\u003c{ key: string | number; doc_count: number; }\u003e\n```\n\n## Why This Library?\nTo highlight the benefits, here's a comparison with/without the library:\n\n\u003cdetails\u003e\n\u003csummary\u003eSame Example Without This Library\u003c/summary\u003e\n\n#### Without providing any types\n\n```ts\nconst result = await client.search(query);\nconst total = result.hits.total; // number | estypes.SearchTotalHits | undefined\nconst firstHit = result.hits.hits[0]._source; // unknown\nconst aggregationBuckets = result.aggregations!.name_counts.buckets; // any, ts error: Object is possibly 'undefined'.\n```\n\n#### With manual type definitions\n\n```ts\nconst result = await client.search\u003c\n  { id: number; created_at: string; },\n  {\n    name_counts: {\n      buckets: Array\u003c{ key: string; doc_count: number }\u003e;\n    };\n  }\n\u003e(query);\n\nconst total = result.hits.total; // number | estypes.SearchTotalHits | undefined\nconst firstHit = result.hits.hits[0]; // { _source: { id: number; created_at: string; } | undefined, fields: Record\u003cstring, unknown\u003e }\nconst aggregationBuckets = result.aggregations!.name_counts.buckets; // Array\u003c{ key: string; doc_count: number; }\u003e\n```\n\n#### With @vahor/typed-es\n\n```ts\n// Automatic type inference - no manual definitions needed\nconst result = await client.search(query);\nconst total = result.hits.total; // number\nconst firstHit = result.hits.hits[0]._source; // { id: number; created_at: string }\nconst aggregationBuckets = result.aggregations.name_counts.buckets; // Array\u003c{ key: string | number; doc_count: number }\u003e \n```\n\n\u003c/details\u003e\n\n## Install\n\n```bash\nbun add @vahor/typed-es\n```\n\nNote: you can install it in dev-dependencies if you don't plan to use the `typedEs` function.\n\n## Usage\n\n\n### Step 1: Define your index types\n\n```ts\ntype CustomIndexes = {\n    \"first-index\": {\n        score: number;\n        entity_id: string;\n        date: string;\n    },\n    \"second-index\": {\n        \"some-field\": string;\n    }\n}\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eFor complex types like \"point\", \"shape\" even \"date\" we currently assume that the type is \u003ccode\u003estring\u003c/code\u003e.\u003c/summary\u003e\n\nex:\n```json\n{\n    \"mappings\": {\n        \"properties\": {\n            \"location\": {\n                \"type\": \"point\"\n            },\n            \"date\": {\n                \"type\": \"date\"\n            }\n        }\n    }\n}\n```\n\nwould give:\n\n```ts\ntype CustomIndexes = {\n\t\"first-index\": {\n\t\tlocation: string;\n\t\tdate: string;\n\t};\n};\n```\n\n\u003c/details\u003e\n\n### Step 2: Create a client\n\n```ts\nimport { Client } from \"@elastic/elasticsearch\";\nimport { TypedClient } from \"@vahor/typed-es\";\n\nconst client = new Client({\n    ... // elasticsearch client config\n}) as unknown as TypedClient\u003cCustomIndexes\u003e;\n```\n\n### Step 3: Use the typedEs function\n\n```ts\nimport { typedEs } from \"@vahor/typed-es\";\n\nconst query = typedEs(client, {\n    index: \"first-index\",\n    _source: [\"score\", \"entity_id\", \"*ate\"],\n});\n\nconst queryWithAggs = typedEs(client, {\n    index: \"first-index\",\n    _source: [\"score\", \"entity_id\", \"*ate\"],\n    aggs: {\n        some_agg: {\n            terms: {\n                field: \"entity_id\",\n            },\n        },\n    },\n});\n```\n\n`typedEs` is a simple wrapper that adds type safety to index, autocompletes on _source. \nCheck its definition in [typed-es.ts](./src/typed-es.ts), you can reuse the same definition to add default values to your queries.\n\nNote: when `_source` is missing, the output will contain every fields.\n\n### Step 4: Enjoy an easy type-safe output\n\n```ts\n// Use the elasticsearch client as usual\nconst output = await client.search(query);\n\n// And without having to add .search\u003cSources, Aggs\u003e(query) everywhere, you now have access to the correct types\nconst hits = output.hits.hits;\nfor (const hit of hits) {\n    // Here hit is typed as { _source: { score: number; entity_id: string, date: string } }\n    const score = hit._source.score; // typed as number\n    const entity_id = hit._source.entity_id; // typed as string\n    const invalid = hit._source.invalid; // error: Property 'invalid' does not exist on type '{ score: number; entity_id: string; }'\n}\n\n\nconst outputWithAggs = await client.search(queryWithAggs);\nconst aggs = outputWithAggs.aggregations;\nconst someAgg = aggs.some_agg;\nconst someAggTerms = someAgg.buckets;\nfor (const bucket of someAggTerms) {\n    // Here bucket is typed as { key: string | number; doc_count: number }\n    const key = bucket.key; // typed as string | number\n    const doc_count = bucket.doc_count; // typed as number\n}\n```\n\nWith this you also get type-errors when you try to access a field that doesn't exist in the index. Or an invalid index.\nAnd with that, also autocompletion for these fields.\n```ts\nconst invalidIndex = typedEs(client, {\n    index: \"invalid-index\", // Here we get a: Type '\"invalid-index\"' is not assignable to type '\"first-index\" | \"second-index\"'. \n    _source: [\"score\", \"entity_id\"],\n});\n```\n\nSee more examples in the test files.\n\n## Usage with `asyncSearch`\n\nThe [asyncSearch](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-async-search-get) API has some complexity for us. The `get` method does not include the original query type information by default.\nTo work around that we've added a new type definition.\n\n```typescript\nconst query = typedEs(...);\n\nconst result = await client.asyncSearch.get\u003ctypeof query\u003e({ id: \"abc\" });\nconst data = result.response; // Same type as if you used client.search(query);\n\n// If you don't have a query variable, you can pass the query type explicitly.\nconst result = await client.asyncSearch.get\u003c{ query: ...}\u003e({ id: \"abc\" });\n```\n\n## Usage with `msearch`\n\nRun multiple searches in a single request with [msearch](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-msearch). The top-level `index` is used as the default. You can override the index per-search using the header that precedes each body.\n\n```ts\n// Assuming `client` is a TypedClient\u003cYourIndexes\u003e\nconst result = await client.msearch({\n\tindex: \"first-index\",\n\tsearches: [\n\t\t// 1) Uses top-level `index`: \"first-index\"\n\t\t{},\n\t\t{ _source: [\"id\", \"name\"] },\n\n\t\t// 2) Override index for this search\n\t\t{ index: \"second-index\" },\n\t\t{ _source: [\"title\"] },\n\t],\n});\n\nconst first = result.responses[0];\nconst doc1 = first.hits.hits[0]._source; // { id: number; name: string }\n\nconst second = result.responses[1];\nconst doc2 = second.hits.hits[0]._source; // { title: string }\n```\n\nNotes:\n- Responses preserve per-search typing: each `responses[i]` matches the corresponding header/body pair.\n- `responses[i]` can be an error object if that search failed.\n\n\u003cdetails\u003e\n    \u003csummary\u003eExample with a dymamic search list\u003c/summary\u003e\n\n```ts\nconst ids = [\"batman\", \"superman\"];\nconst searches = ids.flatMap((id) =\u003e [{}, { query: { match: { id } }, _source: [\"name\"] }] as const);\n//    ^? [{}, { query: { match: { id: \"batman\" | \"superman\" } }, _source: [\"name\"] }]\nconst result = await client.msearch({ index: \"superheroes\", searches);\n\nfor(const match of result.responses) {\n    if(match.hits) {\n\tconst hits = match.hits; // { hits: { _source: { name: string } } }\n    }\n}\n```\n\nNotes:\n- You can still mix indexes, _searches, but here response[i] will be a union of the types of the responses.\n\u003c/details\u003e\n\n## What if the library is missing a feature that you need?\n\nPlease open an issue or a PR.\n\nIf it's a type error and is urgent, you can add the types manually as you'd do without the library.\n\n```typescript\nconst myBrokenQuery = typedEs(client, {\n    index: \"my-index\",\n    _source: [\"score\", \"entity_id\", \"*ate\"],\n});\n\nconst result = await (client as unknown as Client).search\u003cTDocument, TAggregations\u003e(myBrokenQuery); // With the `as Client` cast you are now using the native types\n```\n\n## Limitations\n\n- query fields and aggs fields are not typed.\n- Some agg functions might be missing.\n- _source fields allow any string as you can use wildcards. On the other hand, wildcards will result in the **correct type** in the output.\n- has to use `as unknown as TypedClient\u003cIndexes\u003e` which I don't like.\n- Expect `index` to be a string. Currently we don't support wildcard or `_all` for the index name.\n\n\nPRs are welcome to fix these limitations.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvahor%2Ftyped-es","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvahor%2Ftyped-es","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvahor%2Ftyped-es/lists"}