npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typescript-closure-tools

v0.0.7

Published

Command-line tools to convert closure-style JSDoc annotations to typescript, and to convert typescript sources to closure externs files

Downloads

97

Readme

Use it online

Converts Closure-style JSDoc type annotations to TypeScript definition files.

The purpose of this tool is to assist developers writing TypeScript definitions on large libraries. Our goal is to generate correct type definitions in most cases, and to provide a useful starting point for manually fixing the difficult cases.

Setup

git clone [email protected]:fivetran/typescript-closure-tools.git
cd typescript-closure-tools
git submodule update --init
npm install
node definition-generator/src/main.js test/class.js class.d.ts # Run a single example
sudo npm install -g 

Usage

closure2ts
  [--provides symbols.tsv]
  [--globals output/dir/global-declarations.d.ts]
  [--input_root input/dir]
  [--output_root output/dir]
  [--include_private boolean]
  input/dir/input-file.js output/dir/output-file.d.ts
  input/dir/another-input-file.js output/dir/another-output-file.d.ts
  ...
  • --provides symbols.tsv A tab-separated file where each row has the form file-name.js providedSymbol If this option isn't present, we will simply look for global symbols in the input files.
  • --globals output/dir/global-declarations.d.ts A TypeScript declaration that will be referenced at the top of every output file.
  • --input_root input/dir Root of inputs, considered when computing relative paths for ///<reference path="..." /> tags.
  • --output_root output/dir Root of outputs, considered when computing relative paths for ///<reference path="..." /> tags.
  • --include_private boolean Whether to include items marked as private (@private), defaults to false.

Structure

  • index/ Typescript definition files for the Closure library

definitions-generator/

  • src/ Typescript sources
  • scripts/ Shell scripts used for converting the Closure library
  • test/ Jasmine specs and example JS files used in testing
  • lib/ Dependencies

Running the tests

./scripts/test.sh

Differences between the Closure type system and TypeScript

There are several important differences between the Closure type system and TypeScript.

Differences that are resolved automatically

Static inheritance

In typescript, static properties of classes are inherited:

declare class SuperClass { }
declare module SuperClass {
    var myStaticProperty: number;
}

declare class SubClass extends SuperClass { }

SubClass.myStaticProperty; // : number

In Closure they are not:

/** @constructor */
SuperClass = function() { };
/** @type {string} */
SuperClass.myStaticProperty;
/** @type {string} */
SuperClass.prototype.myInstanceProperty;

/** @extends {SuperClass} */
SubClass = function() { };
goog.inherits(SubClass, SuperClass);

SubClass.myStaticProperty; // undefined

To fix this, we create a common superclass without the static properties:

declare class SuperClass extends SuperClass__Class { }
declare module SuperClass {
    class __Class {  // fake common superclass without myStaticProperty
        myInstanceProperty: string;
    }
    myStaticProperty: string; // static property that won't be inherited by 'extends SuperClass__Class'
}

declare class SubClass extends SubClass__Class { }
declare module SubClass {
    class __Class extends SuperClass__Class { }
}

These fake superclasses don't actually exist and are present solely to simulate the behavior of goog.inherits(SubClass, SuperClass) in TypeScript definition files. Calling new SuperClass__Class or extends SuperClass__Class in non-declaration TypeScript code will generate a runtime error. You should use new SuperClass and extends SuperClass in non-declaration TypeScript code.

Private types

In Closure, the @private annotation is not enforced, and private type definitions, interfaces, classes and enums are often used in public function declarations. Therefore, these private types are included in the TypeScript definition.

Differences that must be fixed manually

Shadowing

In typescript, the current module shadows the global namespace:

declare class MyClass;
declare module myModule {
    class MyClass;
    var myValue : MyClass; // Refers to myModule.MyClass, not global MyClass

This can create problems when referring to global variables that are shadowed by locals:

goog.Error = function() { }

/**
 * @param {Error} e
 */
goog.f = function(e) { };

becomes:

declare module goog {
    class Error { }

    function f(e: Error) { }
}

RequireJS support

Basic RequireJS support is present:

define(function(require, exports, module) {
    /** @param {number} x */
    function functionDeclaration(x) { }
});

becomes:

module MODULE {
    functionDeclaration(x: number): void;
}

Limitations

Declarations are always placed in a module named MODULE

Only symbols with JSDoc annotations are exported

define(function(require, exports, module) {
    /** @type {number} */
    var documentedSymbol = 1;

    var ignoredSymbol = 2;

    exports.documentedSymbol = documentedSymbol;
    exports.ignoredSymbol = 2;
});

becomes:

module MODULE {
    var documentedSymbol: number;
}

exports and module are ignored

Symbols are exported using their local name:

define(function(require, exports, module) {
    /** @type {number} */
    var localName = 1;

    exports.exportedName = localName;
});

becomes:

module MODULE {
    var localName: number;
}