Open darrylnoakes opened 2 years ago
Or even something like the following, where the corresponding type for every key is indexable, with the top-level entries of said type being used as the key/value pairs.
Contrived example:
interface DatabaseSchema extends DBSchema {
posts: Record<string, Post>; // Like `list: { key: string; value: Post }`
metadata: {
times: { joined: string, lastSeen: string };
counts: { posts: number; privateMessages: number };
};
}
This seems doable. A separate generic parameter would need to be introduced for the key. That key can then be used to narrow the type of the value. Here's an updated version of the StoreValue
type and the get
function. If the Key
parameter on the StoreValue
type has a default value of any
, then this isn't a breaking change.
export type StoreValue<
DBTypes extends DBSchema | unknown,
StoreName extends StoreNames<DBTypes>,
Key = any
> = DBTypes extends DBSchema
? (DBTypes[StoreName] & (Key extends StoreKey<DBTypes, StoreName> ? { key: Key } : {}))['value']
: any;
get<
Name extends StoreNames<DBTypes>,
Key extends StoreKey<DBTypes, Name> | IDBKeyRange
>(
storeName: Name,
query: Key
): Promise<StoreValue<DBTypes, Name, Key> | undefined>;
This works on the initial example. When anIDBKeyRange
is used as the key, the value is the full union of types.
Currently, there is no way to strongly type a keyval store that has only certain keys (each with its own value type).
For example:
What I would like is some way for a discriminated union (based on key type, obviously) to be detected and used. The
key
passed to database functions would then be used to provide better typing.One of my other ideas for what this could look like, instead of a discriminated union: