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

How to include custom definition files? #506

Open
BrianLeishman opened this issue Apr 23, 2021 · 3 comments
Open

How to include custom definition files? #506

BrianLeishman opened this issue Apr 23, 2021 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@BrianLeishman
Copy link

We use a service called "heap", that provides just an interface in their documentation for typescript users.

In our project we have a custom @types folder where I've been putting my own index.d.ts files, but so far they've all been just adding things to jQuery, and only for things that already don't have definition files in DefinitelyTyped.

image

In the fancybox/index.d.ts file I have the following

/// <reference types="jquery"/>

declare interface JQueryStatic {
    fancybox: FancyBoxJQueryMethods;
}

and this just kind of magically works with my tscc.spec.json file

{
  "external": {
    "jquery": "$",
    "sweetalert2": "Swal",
    "ladda": "Ladda",
    "luxon": "luxon",
    "intl-tel-input": "intlTelInput",
    "grecaptcha": "grecaptcha",
    "big.js": "Big",
    "axios": "axios",
    "jszip": "JSZip",
    "file-saver": "FileSaver",
  },
  "compilerFlags": {
    "rewrite_polyfills": true,
    "language_out": "ES5_STRICT",
    "compilation_level": "ADVANCED_OPTIMIZATIONS",
    "use_types_for_optimization": true,
    "output_wrapper": "(function(){%output%})()"
  }
}

and my my tsconfig.json

{
    "compilerOptions": {
        "alwaysStrict": true,
        "strict": true,
        "sourceMap": true,
        "noImplicitAny": true,
        "allowJs": false,
        "target": "es5",
        "noEmitOnError": true,
        "lib": [
            "es6",
            "dom"
        ],
        "baseUrl": "./",
        "plugins": [
            {
                "name": "typescript-tslint-plugin",
                "alwaysShowRuleFailuresAsWarnings": false,
                "configFile": "tslint.json",
                "suppressWhileTypeErrorsPresent": false,
                "ignoreDefinitionFiles": true
            }
        ]
    }
}

My heap/index.d.ts file looks like

export declare interface Heap {
    track: (event: string, properties?: Object) => void;
    identify: (identity: string) => void;
    resetIdentity: () => void;
    addUserProperties: (properties: Object) => void;
    addEventProperties: (properties: Object) => void;
    removeEventProperty: (property: string) => void;
    clearEventProperties: () => void;
    appid: string;
    userId: string;
    identity: string | null;
    config: any;
}

declare const heap: Heap;

export default heap;

and using like this

import heap from '../@types/heap/index';

heap.identify(opts.email); // unique identifier
heap.addUserProperties({'Name': opts.name}); // other props

This works great as far as vscodes intellisense goes, but tscc fails with

TSCC: Module name ts.webcore.$001stypes.heap.index$.d$.ts was not provided as a closure compilation source

I tried adding "heap": "heap" to my tscc externs, but that didn't help. I also played around a ton with setting the closure compiler typeRoots, but nothing seemed to change the behavior, and I also stumbled upon this comment that makes me see that that wasn't the correct approach anyway microsoft/TypeScript#12222 (comment).

I also see in the debug output it's re-writing the import as the following, where I'm sure the error is coming from.

var index_1 = goog.require('ts.webcore.$001stypes.heap.index$.d$.ts');

The gluing file being generated is named "heap.js" which contains

goog.module('ts.webcore.$001stypes.heap')
/** Generated by TSCC */
exports = heap;

This led me to try changing the tscc spec extern to "ts/webcore/@types/heap": "heap", but that only renames the gluing file to ts.webcore.$001stypes.heap.js, and I'm guessing that because the name isn't ts.webcore.$001stypes.heap.index$.d$.ts' is where the problem arises. I couldn't figure out how to right the extern in the tscc spec file to get the names to match.

Am I doing something wrong? Is there a way to reference custom type definition files?

@BrianLeishman
Copy link
Author

I also tried the comment here about setting a path in the tsconfig.json to point directly to the custom type microsoft/TypeScript#22217 (comment)

"paths": {
    "heap": ["ts/webcore/@types/heap"],
}

And then changing my import to import heap from 'heap';, which also satisfies the intellisense, but doesn't change the error, and the gluing file turns into this

goog.module('heap')
/** Generated by TSCC */
exports = heap;

which looks like that attempt is going in the opposite direction perhaps.

Side note, but we've been using this for all of our projects since I first started making issues here (lol), and we absolutely love your tool!

@theseanl
Copy link
Owner

In the statement

import heap from '../@types/heap/index';

the imported module name is a relative path, and it refers to a file located there. When tscc collects source files to feed to closure compiler, it looks for the above path and founds nothing (.d.ts file do not emit .js files), hence the error.

In order to have such modules to be considered as external, you have to provide the module's path to the spec file, like below.

{
	"external": {
		"./ts/webcore/@types/heap/index": "heap"
	}
}

Then tscc will create gluing modules and goog.require it whenever a file tries to import the ./ts/webcore/@types/heap/index file. Files in different directory may use different module name to refer to the same module, because module resolution algorithm is in act here.

When a relative path (those starting with ./ or ../) is used as a key in "external" value in spec files, it is resolved from the spec file's location itself, not the current working directory.

@theseanl
Copy link
Owner

In the README, I have mentioned about declaring relative path as an external module, but now I found that it is not very prominent. I guess it'd be nice to elaborate it more with some examples.

@theseanl theseanl added the documentation Improvements or additions to documentation label Jul 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants