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

Conversation

indianakernick
Copy link

This makes some changes to the type declarations so that the value type of an object store can be narrowed based on the key type (and vice versa).

interface Schema extends DBSchema {
  store: {
    key: 'foo';
    value: string;
  } | {
    key: 'bar';
    value: number;
  };
}

// Type of `foo` before this PR:
//   string | number | undefined
// Type of `foo` after this PR:
//   string | undefined
const foo = await db.get('store', 'foo');

// Both of these are fine before this PR but fail to compile after this PR.
await db.put('store', 'string', 'bar');
await db.put('store', 1234, 'foo');

There are some caveats. There's a limitation in the way that TypeScript unions work (see microsoft/TypeScript#18758). It means that the type changes made in this PR cannot be applied to indexes. It also means that narrowing the key type based on a value type when the value type is an object type isn't possible (which affects the typing of add and put).

Also, cursor types haven't been updated. Creating a cursor over one value (for example 'foo') and expecting the value type to be narrowed (string instead of string | number) seems like an obscure use-case. It didn't seem worth the added complexity but I'll implement it if requested. A more common use case would be iterating over multiple values for a single key in an index but we can't do that.

Resolves #275.

It's not possible narrow based on index key types simply because of the way that TypeScript unions work.
Something weird is going on with the function return types. The `Value` type parameter seems to be different depending on whether it's in the parameter type context or the return type context.

Also, removed `IDBKeyRange` from the `add` and `put` methods because that seems to be a mistake. It's not included in lib.dom.d.ts.
I'm not really sure what the problem was or why this solves it but it works!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support discriminated union type or similar in database schemas
1 participant