In the example below I define Typescript types to request data from an index.
There are two performant ways to retrieve a chunk of data from the index server, either by startKey,endKey or by startKey,limit (a count of keys).
I'm doing something wrong when combining these alternate cases to define requests in Typescript and I can't see what, unless my approach to intersect a union doesn't make sense or I don't understand typescript errors.
interface StartKey {
startKey: string;
}
interface EndKey {
endKey: string;
}
interface Limit {
limit: number;
}
type KeyRange = StartKey & EndKey;
type KeyLimit = StartKey & Limit;
type KeyBounds = KeyRange | KeyLimit;
export type Options = {
someparam:string
} & KeyBounds;
function retrieve(options:Options){
const {
startKey,
endKey, //this line causes a compiler error
limit, //this line causes a compiler error
} = options;
}
First of all I create the two alternate interfaces KeyRange (which has endKey) and KeyLimit (which has limit). Then I union those interfaces into a KeyBounds type. That KeyBounds type is then combined by intersection with other index-request-specific parameters when composing a request. For example requesting items using Options should be able to use either one or the other strategy to limit the returned results.
This playground shows the approach I'm currently taking and the surprising (to me) errors that I get from the definition of Options...
- Property 'endKey' does not exist on type 'Options'.
- Property 'limit' does not exist on type 'Options'.
I would expect there to be some path to get endKey OR limit, since Options includes a union of types which have those properties. At most one of them will be present at any one time, but that's just like having an optional property, which doesn't throw a compiler error.
The destructuring which causes the error is exactly when I'm trying to explicitly verify which of the alternate key bounds signatures has been requested, (I'm expecting one or other property to be unset).
By contrast, this code where they are explicitly optional treats the destructuring NOT as an error case, even though the endKey and limit might both be undefined for any particular object. I'm expecting an intersection with a union to result in a similar data structure, except the compiler knows there might be an endKey XOR a limit.
interface KeyRange {
startKey:string
endKey?:string
limit?:string
}
function retrieve(range:KeyRange){
const {
startKey,
endKey,
limit,
} = range;
}
Getting an error that neither exists at all on the resulting type (not even optionally) is surprising to me and suggests I've missed something. Can anyone tell me what I need to do to make these alternates valid?
KeyRange<K> | KeyLimit<K>only overlaps with one propertystartKeyandtype: D["type"];only gives you the extra propertytype- Silvermindtype KeyBounds<K extends Key> = Partial<KeyRange<K>> & Partial<KeyLimit<K>>;- Silvermind