Свойство «Код ошибки» не существует для типа «Событие»

#javascript #typescript #service-worker #indexeddb

Вопрос:

Я создаю сотрудника службы, у которого есть несколько функций, использующих IndexDB. В этих функциях я получаю эти ошибки машинописи:

Property 'errorCode' does not exist on type 'EventTarget'

при использовании db.onsuccess amp; db.onerror

вот мой код работника службы:

 /// <reference no-default-lib="true"/>
/// <reference lib="ES2020" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="webworker" />

export type {};
declare const self: ServiceWorkerGlobalScope;

interface AccessCredentials {
    accessToken: string;
    refreshToken: string;
}

async function getAccessCredentials(): Promise<AccessCredentials> {
    const databaseName = 'BATAccessTokens';
    const databaseStore = 'BATAccessTokens';
    return new Promise((resolve, reject) => {
        const dbrequest = indexedDB.open(databaseName, 1);
        dbrequest.onupgradeneeded = (event) => {
            const database = dbrequest.resu<
            database.createObjectStore(databaseStore, { autoIncrement: true });
            database.onerror = () =>
                reject(`ERROR:  ${event.target.errorCode}`);
        };
        dbrequest.onerror = (event) =>
            reject(`ERROR:  ${event.target.errorCode}`);
        dbrequest.onsuccess = (event) => {
            const database = dbrequest.resu<
            const transaction = database.transaction(databaseStore, 'readwrite');
            const store = transaction.objectStore(databaseStore);
            const request = store.get(1);
            request.onsuccess = () => {
                if (request.result) resolve(request.result);
                resolve(null);
            };
            transaction.oncomplete = () => database.close();
            database.onerror = () => resolve(null);
        };
    });
}

async function putAccessCredentials(credentials: AccessCredentials) {
    const databaseName = 'BATAccessTokens';
    const databaseStore = 'BATAccessTokens';
    return new Promise((resolve, reject) => {
        const dbrequest = indexedDB.open(databaseName, 1);
        dbrequest.onupgradeneeded = () => {
            const database = dbrequest.resu<
            database.createObjectStore(databaseStore, { autoIncrement: true });
            database.onerror = (event) =>
                reject(`ERROR:  ${event.target.errorCode}`);
        };
        dbrequest.onerror = (event) =>
            reject(`ERROR:  ${event.target.errorCode}`);
        dbrequest.onsuccess = (event) => {
            const database = dbrequest.resu<
            const transaction = database.transaction(databaseStore, 'readwrite');
            const store = transaction.objectStore(databaseStore);
            const request = store.put(credentials, 1);
            request.onsuccess = () => resolve(credentials);
            transaction.oncomplete = () => database.close();
            database.onerror = () =>
                reject(`ERROR:  ${event.target.errorCode}`);
        };
    });
}

async function putRBDSCode(RBDSCode) {
    const databaseName = 'BATRBDSCode';
    const databaseStore = 'BATRBDSCode';
    return new Promise((resolve, reject) => {
        const dbrequest = indexedDB.open(databaseName, 1);
        dbrequest.onupgradeneeded = () => {
            const database = dbrequest.resu<
            database.createObjectStore(databaseStore, { autoIncrement: true });
            database.onerror = (event) =>
                reject(`ERROR:  ${event.target.errorCode}`);
        };
        dbrequest.onerror = (event) =>
            reject(`ERROR:  ${event.target.errorCode}`);
        dbrequest.onsuccess = (event) => {
            const database = dbrequest.resu<
            const transaction = database.transaction(databaseStore, 'readwrite');
            const store = transaction.objectStore(databaseStore);
            const request = store.put(RBDSCode, 1);
            request.onsuccess = () => resolve(RBDSCode);
            transaction.oncomplete = () => database.close();
            database.onerror = () =>
                reject(`ERROR:  ${event.target.errorCode}`);
        };
    });
}

async function getClientList(): Promise<readonly WindowClient[]> {
    const clientList = await self.clients.claim().then(() =>
        self.clients.matchAll({
            type: 'window'
        })
    );
    return clientList;
}

self.addEventListener('install', (event) => {
    console.log('Service Worker installed');
});

self.addEventListener('activate', (event) => {
    console.log('Service Worker activated');
});

self.addEventListener('fetch', (event) => {
    if (event.request.method === 'GET' amp;amp; event.request.mode === 'navigate') {
        let request = event.request;
        // console.log({request});

        event.waitUntil(getClientList());

        event.respondWith((async () => {

            const clientList = await getClientList();
            const client = clientList.find((item) => item.visibilityState === 'visible');
            const url = client amp;amp; new URL(client.url);
            const rbdsCode = url amp;amp; url.searchParams.get('RBDSCode');
            const credentials = await getAccessCredentials();

            const dppRequest = false;
            const rbdsRequest = !!rbdsCode amp;amp; !dppRequest;

            if (rbdsRequest amp;amp; !credentials) {
                // console.log(client);
                // client.navigate('/forms/login.html').then(() => client.focus())
                request = new Request(`http://localhost:3000/forms/login.html`);
            }

            if (request amp;amp; credentials) {
                // do something
            }

            if (dppRequest) {
                // handle dpp request
            }

            if (credentials) request = new Request(request, {
                headers: {
                    ...request.headers,
                    Authorization: `Bearer ${credentials.accessToken}`
                }
            });

            const eventResponse = await fetch(request).then((response) => {
                let accessToken, refreshToken;
                for (const header of response.headers.entries()) {
                    if (header[0] === 'accesstoken') accessToken = header[1];
                    if (header[0] === 'refreshtoken') refreshToken = header[1];
                }
                accessToken amp;amp; refreshToken amp;amp; putAccessCredentials({ accessToken, refreshToken });
                return response;
            });

            return eventResponse;
        })());
    }
});
 

Комментарии:

1. Имеет ли значение изменение errorCode , чтобы error что-то изменить? Я спрашиваю, потому что пример, показанный в разделе IDBRequest.onerror , использует имя свойства error для получения дополнительной информации — и предполагает error.target , что оно относится к объекту (запроса), для которого .onerror был установлен.

2. нет, потому что аргумент функции здесь набран в событие, однако я думаю, что нашел обходной путь, используя dbrequest.error.code

3. будьте осторожны с файлом объявления машинописного текста, который вы используете, многие библиотеки машинописного текста содержат неправильные объявления типов для IndexedDB

Ответ №1:

Распаковка ошибки, которую вы видите, немного:

Property 'errorCode' does not exist on type 'EventTarget'

Это имеет смысл, поскольку универсальный EventTarget (например, элемент DOM) не имеет errorCode свойства. Но Typescript здесь вам не поможет, так как он, по-видимому, не знает, какие конкретные типы интерфейсов используются для индексированных объектов БД, когда вы пишете event.target.result .

В этом случае target одно из этих событий является экземпляром IDBRequest… у которого также нет errorCode собственности. Так что вы все равно получили бы аналогичную ошибку.


Как вы обнаружили, у IDBRequest интерфейса действительно есть error свойство, которое является исключением DOMException. В свою очередь, DOMException интерфейс обладает code свойством.

Тем не менее… code свойство устарело — новые типы исключений DOMException не определяют новые коды, поэтому значение code всегда будет равно 0. Вместо этого name следует использовать исключение DOMException, если вам нужно устранить неоднозначность типов ошибок.