Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Narrow types when an object store is declared as a union #291

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 92 additions & 42 deletions src/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,22 +183,48 @@ export type StoreNames<DBTypes extends DBSchema | unknown> =
*
* @template DBTypes DB schema type, or unknown if the DB isn't typed.
* @template StoreName Names of the object stores to get the types of.
* @template Key Key type used for narrowing unions.
*/
export type StoreValue<
DBTypes extends DBSchema | unknown,
StoreName extends StoreNames<DBTypes>,
> = DBTypes extends DBSchema ? DBTypes[StoreName]['value'] : any;
Key = {},
> = DBTypes extends DBSchema
? (DBTypes[StoreName] &
(Key extends DBTypes[StoreName]['key'] ? { key: Key } : {}))['value']
: any;

/**
* Extract database key types from the DB schema type.
*
* @template DBTypes DB schema type, or unknown if the DB isn't typed.
* @template StoreName Names of the object stores to get the types of.
* @template Key Key type used for narrowing unions.
*/
export type StoreKey<
DBTypes extends DBSchema | unknown,
StoreName extends StoreNames<DBTypes>,
> = DBTypes extends DBSchema ? DBTypes[StoreName]['key'] : IDBValidKey;
Key = {},
> = DBTypes extends DBSchema
? Key extends DBTypes[StoreName]['key']
? Key & DBTypes[StoreName]['key']
: DBTypes[StoreName]['key']
: IDBValidKey;

/**
* Extract database key types from the DB schema type.
*
* @template DBTypes DB schema type, or unknown if the DB isn't typed.
* @template StoreName Names of the object stores to get the types of.
* @template Value Value type used for narrowing unions.
*/
export type StoreKeyFromValue<
DBTypes extends DBSchema | unknown,
StoreName extends StoreNames<DBTypes>,
Value extends StoreValue<DBTypes, StoreName>,
> = DBTypes extends DBSchema
? (DBTypes[StoreName] & { value: Value })['key']
: IDBValidKey;

/**
* Extract the names of indexes in certain object stores from the DB schema type.
Expand Down Expand Up @@ -337,11 +363,14 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param value
* @param key
*/
add<Name extends StoreNames<DBTypes>>(
add<
Name extends StoreNames<DBTypes>,
Value extends StoreValue<DBTypes, Name>,
>(
storeName: Name,
value: StoreValue<DBTypes, Name>,
key?: StoreKey<DBTypes, Name> | IDBKeyRange,
): Promise<StoreKey<DBTypes, Name>>;
value: Value,
key?: StoreKeyFromValue<DBTypes, Name, Value>,
): Promise<StoreKeyFromValue<DBTypes, Name, Value>>;
/**
* Deletes all records in a store.
*
Expand Down Expand Up @@ -406,10 +435,13 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param storeName Name of the store.
* @param query
*/
get<Name extends StoreNames<DBTypes>>(
get<
Name extends StoreNames<DBTypes>,
Key extends StoreKey<DBTypes, Name> | IDBKeyRange,
>(
storeName: Name,
query: StoreKey<DBTypes, Name> | IDBKeyRange,
): Promise<StoreValue<DBTypes, Name> | undefined>;
query: Key,
): Promise<StoreValue<DBTypes, Name, Key> | undefined>;
/**
* Retrieves the value of the first record in an index matching the query.
*
Expand Down Expand Up @@ -440,11 +472,14 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param query
* @param count Maximum number of values to return.
*/
getAll<Name extends StoreNames<DBTypes>>(
getAll<
Name extends StoreNames<DBTypes>,
Key extends StoreKey<DBTypes, Name> | IDBKeyRange | null,
>(
storeName: Name,
query?: StoreKey<DBTypes, Name> | IDBKeyRange | null,
query?: Key,
count?: number,
): Promise<StoreValue<DBTypes, Name>[]>;
): Promise<StoreValue<DBTypes, Name, Key>[]>;
/**
* Retrieves all values in an index that match the query.
*
Expand Down Expand Up @@ -475,11 +510,14 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param query
* @param count Maximum number of keys to return.
*/
getAllKeys<Name extends StoreNames<DBTypes>>(
getAllKeys<
Name extends StoreNames<DBTypes>,
Key extends StoreKey<DBTypes, Name> | IDBKeyRange | null,
>(
storeName: Name,
query?: StoreKey<DBTypes, Name> | IDBKeyRange | null,
query?: Key,
count?: number,
): Promise<StoreKey<DBTypes, Name>[]>;
): Promise<StoreKey<DBTypes, Name, Key>[]>;
/**
* Retrieves the keys of records in an index matching the query.
*
Expand Down Expand Up @@ -511,10 +549,13 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param storeName Name of the store.
* @param query
*/
getKey<Name extends StoreNames<DBTypes>>(
getKey<
Name extends StoreNames<DBTypes>,
Key extends StoreKey<DBTypes, Name> | IDBKeyRange,
>(
storeName: Name,
query: StoreKey<DBTypes, Name> | IDBKeyRange,
): Promise<StoreKey<DBTypes, Name> | undefined>;
query: Key,
): Promise<StoreKey<DBTypes, Name, Key> | undefined>;
/**
* Retrieves the key of the first record in an index that matches the query.
*
Expand Down Expand Up @@ -547,11 +588,14 @@ export interface IDBPDatabase<DBTypes extends DBSchema | unknown = unknown>
* @param value
* @param key
*/
put<Name extends StoreNames<DBTypes>>(
put<
Name extends StoreNames<DBTypes>,
Value extends StoreValue<DBTypes, Name>,
>(
storeName: Name,
value: StoreValue<DBTypes, Name>,
key?: StoreKey<DBTypes, Name> | IDBKeyRange,
): Promise<StoreKey<DBTypes, Name>>;
value: Value,
key?: StoreKeyFromValue<DBTypes, Name, Value>,
): Promise<StoreKeyFromValue<DBTypes, Name, Value>>;
}

type IDBPTransactionExtends = Omit<
Expand Down Expand Up @@ -638,10 +682,13 @@ export interface IDBPObjectStore<
*/
add: Mode extends 'readonly'
? undefined
: (
value: StoreValue<DBTypes, StoreName>,
key?: StoreKey<DBTypes, StoreName> | IDBKeyRange,
) => Promise<StoreKey<DBTypes, StoreName>>;
: <
Value extends StoreValue<DBTypes, Name>,
Name extends StoreName = StoreName,
>(
value: Value,
key?: StoreKeyFromValue<DBTypes, Name, Value>,
) => Promise<StoreKeyFromValue<DBTypes, Name, Value>>;
/**
* Deletes all records in store.
*/
Expand Down Expand Up @@ -675,37 +722,37 @@ export interface IDBPObjectStore<
*
* Resolves with undefined if no match is found.
*/
get(
query: StoreKey<DBTypes, StoreName> | IDBKeyRange,
): Promise<StoreValue<DBTypes, StoreName> | undefined>;
get<Key extends StoreKey<DBTypes, StoreName> | IDBKeyRange>(
query: Key,
): Promise<StoreValue<DBTypes, StoreName, Key> | undefined>;
/**
* Retrieves all values that match the query.
*
* @param query
* @param count Maximum number of values to return.
*/
getAll(
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
getAll<Key extends StoreKey<DBTypes, StoreName> | IDBKeyRange | null>(
query?: Key,
count?: number,
): Promise<StoreValue<DBTypes, StoreName>[]>;
): Promise<StoreValue<DBTypes, StoreName, Key>[]>;
/**
* Retrieves the keys of records matching the query.
*
* @param query
* @param count Maximum number of keys to return.
*/
getAllKeys(
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
getAllKeys<Key extends StoreKey<DBTypes, StoreName> | IDBKeyRange | null>(
query?: Key,
count?: number,
): Promise<StoreKey<DBTypes, StoreName>[]>;
): Promise<StoreKey<DBTypes, StoreName, Key>[]>;
/**
* Retrieves the key of the first record that matches the query.
*
* Resolves with undefined if no match is found.
*/
getKey(
query: StoreKey<DBTypes, StoreName> | IDBKeyRange,
): Promise<StoreKey<DBTypes, StoreName> | undefined>;
getKey<Key extends StoreKey<DBTypes, StoreName> | IDBKeyRange>(
query: Key,
): Promise<StoreKey<DBTypes, StoreName, Key> | undefined>;
/**
* Get a query of a given name.
*/
Expand Down Expand Up @@ -749,10 +796,13 @@ export interface IDBPObjectStore<
*/
put: Mode extends 'readonly'
? undefined
: (
value: StoreValue<DBTypes, StoreName>,
key?: StoreKey<DBTypes, StoreName> | IDBKeyRange,
) => Promise<StoreKey<DBTypes, StoreName>>;
: <
Value extends StoreValue<DBTypes, Name>,
Name extends StoreName = StoreName,
>(
value: Value,
key?: StoreKeyFromValue<DBTypes, Name, Value>,
) => Promise<StoreKeyFromValue<DBTypes, Name, Value>>;
/**
* Iterate over the store.
*/
Expand Down
Loading