Closed akomm closed 3 months ago
Example:
import {ArangoApiResponse} from "arangojs/connection"
import {
EnsureGeoIndexOptions,
EnsureInvertedIndexOptions,
EnsurePersistentIndexOptions,
EnsureTtlIndexOptions,
EnsureZkdIndexOptions,
Index
} from "arangojs/indexes"
type TaggedLookup<TType extends {type: string}> = {
[TTag in TType["type"]]: TType extends {type: TTag} ? TType : never
}
type EnsureIndexOptions =
| EnsurePersistentIndexOptions
| EnsureGeoIndexOptions
| EnsureTtlIndexOptions
| EnsureZkdIndexOptions
| EnsureInvertedIndexOptions
type EnsureIndexResult = TaggedLookup<Index>
declare function ensureIndex<TOptions extends EnsureIndexOptions>(
options: TOptions
): Promise<
ArangoApiResponse<
EnsureIndexResult[TOptions["type"]] & {isNewlyCreated: boolean}
>
>
declare const input0: EnsureIndexOptions // union
declare const input1: EnsurePersistentIndexOptions
declare const input2: EnsureGeoIndexOptions
declare const input3: EnsureTtlIndexOptions
declare const input4: EnsureZkdIndexOptions
declare const input5: EnsureInvertedIndexOptions
const index1 = ensureIndex(input1) // knows result is persistent index
const index2 = ensureIndex(input2) // knows result is geo index
const index3 = ensureIndex(input3) // knows result is ttl index
const index4 = ensureIndex(input4) // knows result is zkd index
const index5 = ensureIndex(input5) // knows result is inverted index
function takesEnsureIndexOptions<TOptions extends EnsureIndexOptions>(opts: TOptions) {
return ensureIndex(opts)
}
const index6 = takesEnsureIndexOptions(input0) // knows result is one of persistent, geo, ttl, zkd or inverted index
const index7 = takesEnsureIndexOptions(input1) // knows result is persistent index
Is there any chance for the fix to get into the repository, if there was a PR?
Here example: TS Playground
import type {ArangoApiResponse} from "arangojs/connection"
import type {
EnsureGeoIndexOptions,
EnsureInvertedIndexOptions,
EnsurePersistentIndexOptions,
EnsureTtlIndexOptions,
EnsureZkdIndexOptions,
EnsureFulltextIndexOptions,
PersistentIndex,
TtlIndex,
GeoIndex,
InvertedIndex,
ZkdIndex
FulltextIndex
} from "arangojs/indexes"
// 1. add type here if needed
type EnsureIndexOptions =
EnsurePersistentIndexOptions |
EnsureTtlIndexOptions |
EnsureGeoIndexOptions |
EnsureInvertedIndexOptions |
EnsureZkdIndexOptions |
EnsureFulltextIndexOptions // deprecated, but for completness
// 2. add result for ensureIndex here
type EnsureIndexResult = {
persistent: Promise<ArangoApiResponse<PersistentIndex & {isNewlyCreated: boolean}>>
ttl: Promise<ArangoApiResponse<TtlIndex & {isNewlyCreated: boolean}>>,
geo: Promise<ArangoApiResponse<GeoIndex & {isNewlyCreated: boolean}>>,
inverted: Promise<ArangoApiResponse<InvertedIndex & {isNewlyCreated: boolean}>>,
zkd: Promise<ArangoApiResponse<ZkdIndex & {isNewlyCreated: boolean}>>
fulltext: Promise<ArangoApiResponse<FulltextIndex & {isNewlyCreated: boolean}>>
}
// 3. no need to change this one any longer
// You can't pass in what is not defined in 1.
// You get type error on *return type*, when you forget to sync 1. & 2.
declare function ensureIndex<TOptions extends EnsureIndexOptions>(details: TOptions): EnsureIndexResult[TOptions['type']]
The doc can either be merged on ensureIndex
with each type example, or moved to the type
property, as its what you would typically start with if you don't know the exact shape or options yet.
oh, wow
There are currently two problems with the signature of
ensureIndex
EnsurePersistentIndexOptions
andEnsureGeoIndexOptions
exist, but no union type that combines the options. For example:type EnsureIndexOptions = EnsurePersistentIndexOptions | EnsureGeoIndexOptions | ...
ensureIndex
is unnecessary because the options are fit to be a tagged union.Because you use overloading (2.) instead of using a union (which would also solve the problem 1.), this is not possible:
You need to always consider your API is not used inline and the type is inferred, but also wrapped by some consumer logic. The current design is very limited in this way.
Example of the consequences and what is needed because of overloading:
Its also possible to map the Options to the Return type using conditionals. I assume that was the initial consideration when the overload API was picked? Maybe it was not possible at that time?