cordova-plugin-file icon indicating copy to clipboard operation
cordova-plugin-file copied to clipboard

Adjust type definitions to work without type imports

Open kputh opened this issue 5 years ago • 1 comments
trafficstars

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

  • cordova-plugin-file 6.0.2
  • typescript 3.8.3

Checklist

  • [x] I searched for existing GitHub issues
  • [ ] I updated all Cordova tooling to most recent version
  • [x] I included all the necessary information above

kputh avatar Jun 24 '20 17:06 kputh

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.

breautek avatar Aug 06 '20 09:08 breautek