apache / cordova-plugin-file

Apache Cordova File Plugin
https://cordova.apache.org/
Apache License 2.0
740 stars 757 forks source link

Adjust type definitions to work without type imports #402

Open kputh opened 3 years ago

kputh commented 3 years ago

Bug Report

Problem

What is expected to happen?

The following code should compile without adding any imports:

export async function resolveLocalFileSystemURL(url: string): Promise<Entry> {
    if ('function' !== typeof window?.resolveLocalFileSystemURL) {
        throw new Error('window.resolveLocalFileSystemURL is not a function');
    }
    return new Promise((resolve, reject) => window.resolveLocalFileSystemURL(url, resolve, reject));
}

export async function getDirectory(directoryEntry: DirectoryEntry,
                                   path: string, options?: Flags): Promise<DirectoryEntry> {
    return new Promise((resolve, reject) => directoryEntry.getDirectory(path, options, resolve, reject));
}

What does actually happen?

error TS2304: Cannot find name 'Entry'.
error TS2339: Property 'resolveLocalFileSystemURL' does not exist on type 'Window & typeof globalThis'.
error TS2339: Property 'resolveLocalFileSystemURL' does not exist on type 'Window & typeof globalThis'.
error TS2304: Cannot find name 'DirectoryEntry'.
error TS2304: Cannot find name 'Flags'.
error TS2304: Cannot find name 'DirectoryEntry'.

Information

It seems that I cannot use this plugin without explicitly importing the type declarations. But (most) import syntaxes are meant to import types and implementations – the latter not being provided in any way by npm standards.

(When I add import 'cordova-plugin-file'; it tells me that the definition file is no module. /// <reference types="cordova-plugin-file" /> works, but arriving at this workaround took quite a while.)

When I use cordova-sqlite-storage with the types from DefinitelyTyped, it works out of the box and without any imports:

export async function openDatabase(args: SQLitePlugin.OpenArgs): Promise<AsyncDatabase> {
    if ('function' !== typeof window?.sqlitePlugin?.openDatabase) {
        throw new Error('window.sqlitePlugin.openDatabase is not a function');
    }
    return new Promise((resolve, reject) =>
        window.sqlitePlugin.openDatabase(args, db => resolve(new AsyncDatabase(db)), reject));
}

The difference is likely the namespace declaration in cordova-sqlite-storage's type definition file.

Version information

Checklist

breautek commented 3 years ago

When I use cordova-sqlite-storage with the types from DefinitelyTyped, it works out of the box and without any imports:

What's actually happening here is that when you install @types/cordova-sqlite-storage or any other typings from the @types organization, they get placed in node_modules/@types/... which typescript will automatically load by default.

Typings that is provided by cordova-plugin-file I believe is only ever imported when you explicitly have an import statement (which doesn't make sense in this case as cordova plugins don't actually export anything, as they clobber the global namespace).

Using /// <reference types="cordova-plugin-file" /> like you said should work. You can also try messing with the typeRoots TS compiler flag.

There isn't anything Cordova can "adjust" to make this work out of the box. But I do believe this should be documented somewhere so I'll leave this issue open.