jakearchibald / idb

IndexedDB, but with promises
https://www.npmjs.com/package/idb
ISC License
6.22k stars 348 forks source link

IDBPObjectStore cannot be passed to functions #241

Closed ricochet1k closed 2 years ago

ricochet1k commented 2 years ago

I want to be able to write a function to set up some indexes common to a bunch of tables in the schema, but it seems the types somewhere may be too specific.

import * as idb from 'idb';

// doesn't work:
// interface Schema extends idb.DBSchema {

type Schema = {
    foos: {
        key: string,
        value: any,
        indexes: [
            something: string,
        ]
    };
    bars: {
        key: string,
        value: any,
        indexes: [
            something: string,
        ]
    };
    bazs: {
        key: string,
        value: any,
        indexes: [
            other: string,
        ]
    };
}

type SomethingKeys = 'foos' | 'bars';

function initStore(store: idb.IDBPObjectStore<Schema, any, SomethingKeys, 'versionchange'>) {
    store.createIndex('something', 'something');
}

idb.openDB<Schema>("asdf", 1, {
    upgrade(db) {
        let foos = db.createObjectStore("foos");
        initStore(foos);

        let bars = db.createObjectStore("bars");
        initStore(bars);
    }
});

First of all, when I try to do it as the docs suggest with interface Schema extends idb.DBSchema I get

Property 'foos' of type '{ key: string; value: any; indexes: [something: string]; }' is not assignable to 'string' index type 'DBSchemaValue'.ts(2411)

The code as it is gives me this:

Argument of type 'IDBPObjectStore<Schema, ArrayLike<string>, "foos", "versionchange">' is not assignable to parameter of type 'IDBPObjectStore<Schema, any, SomethingKeys, "versionchange">'.
  The types returned by 'createIndex(...).openCursor(...)' are incompatible between these types.
    Type 'Promise<IDBPCursorWithValue<Schema, ArrayLike<string>, "foos", any, "versionchange">>' is not assignable to type 'Promise<IDBPCursorWithValue<Schema, any, SomethingKeys, any, "versionchange">>'.
      Type 'IDBPCursorWithValue<Schema, ArrayLike<string>, "foos", any, "versionchange">' is not assignable to type 'IDBPCursorWithValue<Schema, any, SomethingKeys, any, "versionchange">'.
        The types returned by '[Symbol.asyncIterator]()' are incompatible between these types.
          Type 'AsyncIterableIterator<IDBPCursorWithValueIteratorValue<Schema, ArrayLike<string>, "foos", any, "versionchange">>' is not assignable to type 'AsyncIterableIterator<IDBPCursorWithValueIteratorValue<Schema, any, SomethingKeys, any, "versionchange">>'.
            Type 'IDBPCursorWithValueIteratorValue<Schema, ArrayLike<string>, "foos", any, "versionchange">' is not assignable to type 'IDBPCursorWithValueIteratorValue<Schema, any, SomethingKeys, any, "versionchange">'.
              Types of property 'source' are incompatible.
                Type 'IDBPObjectStore<Schema, ArrayLike<string>, "foos", "versionchange"> | IDBPIndex<Schema, ArrayLike<string>, "foos", any, "versionchange">' is not assignable to type 'IDBPObjectStore<Schema, any, SomethingKeys, "versionchange"> | IDBPIndex<Schema, any, SomethingKeys, any, "versionchange">'.
                  Type 'IDBPObjectStore<Schema, ArrayLike<string>, "foos", "versionchange">' is not assignable to type 'IDBPObjectStore<Schema, any, SomethingKeys, "versionchange"> | IDBPIndex<Schema, any, SomethingKeys, any, "versionchange">'.ts(2345)

This is a reduced test case from a project, where I actually get a simpler error message:

Argument of type 'IDBPObjectStore<{ Course: { key: string; value: PropertiesType<{ name: "string"; }>; indexes: Merge<{ _id: string; }, { '[_local_updated+_id]': [Date, string]; }>; }; } & { __replication: ReplicationTable; } & ... 4 more ... & { ...; }, ArrayLike<...>, "Course", "versionchange">' is not assignable to parameter of type 'IDBPObjectStore<{ Course: { key: string; value: PropertiesType<{ name: "string"; }>; indexes: Merge<{ _id: string; }, { '[_local_updated+_id]': [Date, string]; }>; }; } & { __replication: ReplicationTable; } & ... 4 more ... & { ...; }, any, ReplicableTables, "versionchange">'.
  Types of property 'indexNames' are incompatible.
    Type 'TypedDOMStringList<"_id" | "[_local_updated+_id]">' is not assignable to type 'TypedDOMStringList<"[_local_updated+_id]">'.ts(2345)

Is there a reason you are using TypedDOMStringList instead of ArrayLike? TypedDOMStringList probably is a problem because T appears in both covariant and contravariant positions (function return and parameter types).

jakearchibald commented 2 years ago

indexes takes an object, not an array.

Your version vs correct version.