Giter Site home page Giter Site logo

clutz's Introduction

Clutz - Closure to TypeScript Declarations (.d.ts) generator.

Clutz has been archived, which means the repository is in a read-only state. Clutz will not receive updates, and issues and pull requests will be locked.

We don’t believe that Clutz satisfies the needs of the open-source community. The use-case it was designed for is very limited, and only works with the full stack of Google TypeScript tooling. Clutz has also proven to be difficult to use: due to the tight integration with Closure Compiler it is only usable when building the latest versions of each. Additionally, many have tried to use it as a general JavaScript to TypeScript migrator and it fails at this.

We have updated the default branch to be buildable so that existing users may continue using Clutz as-is.

This project uses the Closure Compiler to parse Closure-style JSDoc type annotations from ES5/ES2015 code, and generates a suitable TypeScript type definition file (.d.ts) for the exported API.

The intent is to allow TypeScript code to import libraries written with Closure-style type declarations. Having the clutz generated declarations allows type-checking in the TypeScript compiler and IDE tooling (for highlighting errors and type-sensitive auto-complete) as if the imported code was written in TypeScript.

Supported versions

We lack the resources to make Clutz releases or support multiple versions of dependent tools simultaneously. You'll have the most success with Clutz if you use it with:

  • Closure Compiler at HEAD: whatever maven thinks -SNAPSHOT is.
  • A recent version of TypeScript: the test suite runs against the version of typescript in npm-shrinkwrap.json, so that is always a good choice.

Example usage

We don't offer a binary distribution, so first you need to build from source. From the root directory run:

$ npm install
$ ./gradlew build installDist # or just "gradlew" on Windows
...
BUILD SUCCESSFUL

You can use Clutz from the command line using the wrapper script produced by Grade or by executing the JAR file in build/libs/ yourself. Here is a sample execution:

$ PATH=$PATH:./build/install/clutz/bin
$ clutz path/to/my/source1.js path/to/my/source2.js ...
        --externs path/to/closure-compiler/externs/es3.js path/to/closure-compiler/externs/es5.js ...
        -o out.d.ts

This creates TypeScript type definitions in out.d.ts for all the closure types discovered in the inputs. Symbols which were declared with goog.provide('x') may be imported in TypeScript as import x from 'goog:x';. For full explanation of what TypeScript types are produced for different Closure usages, see the .js and .d.ts files in src/test/com/google/javascript/clutz.

When compiling TypeScript code that depends on the closure code, include the src/resources/closure.lib.d.ts file along with out.d.ts.

Note that clutz requires that your code can be compiled with Closure Compiler. If you get errors, try reproducing them without clutz, by compiling your code with Closure alone. The arguments for invoking clutz are intentionally similar to the arguments for invoking the Closure compiler. You can find the additional compiler flags that clutz passes to Closure Compiler in src/main/java/com/google/javascript/clutz/Options.java. If the failure is reproducible this way, then you have a closure type error in your code (or a bug in Closure Compiler).

Gents - Closure to TypeScript converter

This repository also hosts gents - tool that generates TypeScript code out of Closure annotated .js. We host it in this repo together with clutz because they both wrap Closure Compiler to get the type information. As such gents shares clutz restriction that it only accepts code that is valid well-typed Closure JavaScript.

Details about some specific conversions follow:

Module Conversion

gents converts Closure goog.module and goog.provide module/namespaces into TypeScript modules. On the exporting side, it converts export assignments into TypeScript export statements. On the importing side, it converts goog.require statements into TypeScript imports. Due to naming issues, this may result in the renaming of the imported symbols.

// file a.js
goog.module('mod.A');
exports = function(n) { return n; };

// file b.js
goog.provide('provided.B');
provided.B.val = 4;

// file c.js
goog.module('importer.C');
var A = goog.require('mod.A');
var B = goog.require('provided.B');

/** @type {number} */
var num = A(B.val);

Is converted to:

// file a.ts
export const A = function(n) { return n; };

// file b.ts
export const val = 4;

// file c.ts
export {};
import {A} from "./a";
import * as B from "./b";

let num: number = A(B.val);

Class Conversion

gents converts @constructor annotated functions and goog.defineClass into ES6 class declarations. Additionally, it moves all prototype and static method/field declarations into the class.

/**
 * @param {number} n
 * @constructor
 */
function A(n) {
  /** @type {number} */
  this.num = n;
}

/** @return {number} */
A.prototype.foo = function() { return 4; };
/** @return {boolean} */
A.bar = function() { return false; };
/** @type {boolean} */
A.x = true;

Is converted to:

class A {
  num: number;
  static x: boolean = true;

  constructor(n: number) {
    this.num = n;
  }
  foo(): number {
    return 4;
  }
  static bar(): boolean {
    return false;
  }
}

Type Conversion

gents converts JSDoc annotated JavaScript into the proper TypeScript declaration. Note that just like with classes, gents only converts explicitly annotated types. This is to make sure gents doesn't accidentally aggressively infer the types of every variable and generate giant type declarations.

Known Issues and TODOs

Github issues

clutz's People

Contributors

alexeagle avatar bowenni avatar devversion avatar domesticmouse avatar dominickramer avatar dpurp avatar drjkl avatar dzinxed avatar evmar avatar gmoothart avatar goodwine avatar jdramaix avatar jermowery avatar jjudd avatar lambertjamesd avatar lauraharker avatar lucassloan avatar mariakhomenko avatar matrixfrog avatar mprobst avatar naomiblack avatar nbeloglazov avatar obsc avatar rehmsen avatar rictic avatar rkirov avatar tadeegan avatar teppeis avatar vrana avatar whymarrh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clutz's Issues

TS enforces generic type params are present; closure doesnt

Lots of instance of this javascript/closure/ui/ac/ac.jslib.d.ts:1409:NaN: Generic type 'EventId<T>' requires 1 type argument(s).
and more:
javascript/closure/ui/ac/ac.jslib.d.ts:606:NaN: Generic type 'EventHandler<SCOPE>' requires 1 type argument(s).
javascript/closure/ui/ac/ac.jslib.d.ts:1593:NaN: Generic type 'Promise<TYPE, RESOLVER_CONTEXT>' requires 2 type argument(s).
javascript/closure/ui/ac/ac.jslib.d.ts:1736:NaN: Generic type 'Array<T>' requires 1 type argument(s).
etc.

We might be able to determine that the number of type arguments isn't correct by looking at the type the arguments are passed to, and replace the missing ones with 'any'.
Given the number of occurrences (34 in this particular compile) I don't think we want to try to fix all the usage sites.

Self-referencing classes

in provide_single_class.js

/**
 * @param {foo.bar.Baz} b
 * @return {boolean}
 */
foo.bar.Baz.prototype.equals = function(b) {
  return false;
};

emits

declare namespace ಠ_ಠ.cl2dts_internal.foo.bar {
  class Baz {
    field : string ;
    equals (b : foo.bar.Baz ) : boolean ;
    method (a : string ) : number ;
    static staticMethod (a : string ) : number ;
  }
}

the Baz name is not correctly qualified, should probably be bare Baz or maybe fully-qualified with the look of disapproval

Reference to nested enum broken by recent change

in https://github.com/google/closure-library/blob/master/closure/goog/events/wheelevent.js
we see

/**
 * @param {goog.events.WheelEvent.DeltaMode} deltaMode The delta mode units of
 *     the wheel event.
 * @constructor
 */
goog.events.WheelEvent = function(
    browserEvent, deltaMode, deltaX, deltaY, deltaZ) {

We emit

declare namespace ಠ_ಠ.cl2dts_internal.goog.events {
  class WheelEvent extends BrowserEvent {
    constructor (browserEvent : Event , deltaMode : WheelEvent.DeltaMode , deltaX : number , deltaY : number , deltaZ : number ) ;
    deltaMode : WheelEvent.DeltaMode ;
    type : WheelEvent.EventType ;
    static PIXELS_PER_PAGE_ : number ;
    /* not emitting EventType because it is an enum and it is not provided */
    /* not emitting DeltaMode because it is an enum and it is not provided */
    static PIXELS_PER_LINE_ : number ;
  }
}
declare module 'goog:goog.events.WheelEvent' {
  import alias = ಠ_ಠ.cl2dts_internal.goog.events.WheelEvent;
  export default alias;
}

And this is broken because DeltaMode and EventType are omitted and don't appear anywhere else.

Similar to the report in #71 and probably broken by our fix to #69

Index out of bounds

Caused by: java.lang.RuntimeException: Failed to emit type goog.ui.ac.Renderer
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:725)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitUnionType(DeclarationGenerator.java:773)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.access$1100(DeclarationGenerator.java:388)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseUnionType(DeclarationGenerator.java:606)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseUnionType(DeclarationGenerator.java:566)
    at com.google.javascript.rhino.jstype.UnionType.visit(UnionType.java:601)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:723)
    ... 24 more
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(String.java:1918)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.getRelativeName(DeclarationGenerator.java:401)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.access$1000(DeclarationGenerator.java:388)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseObjectType(DeclarationGenerator.java:597)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseObjectType(DeclarationGenerator.java:566)
    at com.google.javascript.rhino.jstype.ObjectType.visit(ObjectType.java:524)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:723)

duplicate output for interface with nested enum

see goog.fx.Transition (interface) and goog.fx.Transition.EventType (enum).

Output is

declare namespace ಠ_ಠ.cl2dts_internal.goog.fx {                                                      
  interface Transition {                                                                             
    play : any ;                                                                                     
    stop : any ;                                                                                     
  }                                                                                                  
  var Transition : { EventType : Transition.EventType }                                              
}  

declare namespace ಠ_ಠ.cl2dts_internal.goog.fx.Transition {...}

I think it is safe to assume that nested classes, enums, and interfaces will have their own goog.provide and plainly skip them from the properties of the parent classes, enums, interfaces.

In this case Transition.EventType is provided explicitly.

fail to find symbol for a provided object literal

js:

goog.provide('goog.color.names');

goog.color.names = {
    'aliceblue': '#f0f8ff',
    'antiquewhite': '#faebd7'
};

error:

java.lang.IllegalArgumentException: goog.provide not defined: goog.color.names
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:145)
    at com.google.javascript.cl2dts.DeclarationGenerator.produceDts(DeclarationGenerator.java:153)

in the debugger, can see

topScope.getOwnSlot("goog.color") -> Var goog.color{{names: {aliceblue: string, antiquewhite: string}}}
topScope.getOwnSlot("goog.color.names") -> null
topScope.getOwnSlot("goog.color.names.aliceblue") -> Var goog.color.names.aliceblue{string}

subclasses with different constructor params break static call method gen

For example if B extends A and takes string instead of number, we generate:

declare namespace f {
    class A {
        constructor(n: number);
        static call(a: A, n: number);
    }

    class B extends A {
        constructor(s: string);
        static call(b: B, n: string);
    }
}

TS barfs on the static call for B which is required to subtype A's functional type. See 'oog.fx.dom.PredefinedEffect' and 'Animation' for closure lib repro.

Maybe we should not output call and apply for constructor functions until someone really needs them. I can't come up with a good need for using those in sane TS code.

Provided enum static emit

browserevent.js

goog.provide('goog.events.BrowserEvent');
goog.provide('goog.events.BrowserEvent.MouseButton');
/**
 * @constructor
 * @extends {goog.events.Event}
 */
goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
}
/**
 * Normalized button constants for the mouse.
 * @enum {number}
 */
goog.events.BrowserEvent.MouseButton = {
  LEFT: 0,
  MIDDLE: 1,
  RIGHT: 2
};

we emit

  class BrowserEvent extends Event {
    isButton (a : BrowserEvent.MouseButton ) : boolean ;
    static MouseButton : BrowserEvent.MouseButton ;
  }

should be something like (if valid)

declare namespace goog.events {
class BrowserEvent {
  isButton (a: goog.events.BrowserEvent.MouseButton) {
}

declare namespace goog.events.BrowserEvent {
enum MouseButton {
 }
}

Emitting a symbol which isn't provided

I added a bit of debug to show what the provides are, and ran on javascript/closure/events/events.js

// Processing provides [goog.events, goog.events.CaptureSimulationMode, goog.events.Key, goog.events.ListenableType] from input javascript/closure/events/events.js
declare namespace ಠ_ಠ.cl2dts_internal.goog.events {
...
 class BrowserEvent extends Event {

But BrowserEvent is not goog.provide'd from this file, and in fact it is in a different file.

`@dict` constructors with additional properties

Currently the closure code below produces (AFAICT) only {[k: string]: any}. We should include all other defined constructor properties in the generated type, and only include the property accessor on top of that.

E.g.:

/** @dict @constructor */
X = function() {};
X.prototype.foo = function() {};

Should be:

class X {
  [k: string]: any;
  foo();
}

Support `goog.require` calls by overloading the function

To typecheck user code, written in closure module style:

var {trim} = goog.require('goog.string');

we can do so by emitting:

declare namespace ಠ_ಠ.cl2dts_internal.goog {
  function require(name: string): any;
  function require(name: 'goog.string'): typeof ಠ_ಠ.cl2dts_internal.goog.string;
}

nested classes without provide

/**
 * @constructor
 * @struct
 * @final
 * @implements {goog.Thenable<TYPE>}
 * @template TYPE,RESOLVER_CONTEXT
 */
goog.Promise = function(resolver, opt_context) {
/**
 * @private @final @struct @constructor
 */
goog.Promise.CallbackEntry_ = function() {}
}

produces a static member:

class Promise < TYPE , RESOLVER_CONTEXT > implements Thenable {
static CallbackEntry_ ( ) : void ;

Emitting static members on interface

/**
 * An interface that describes a single registered listener.
 * @interface
 */
goog.events.ListenableKey = function() {};

/**
 * Reserves a key to be used for ListenableKey#key field.
 * @return {number} A number to be used to fill ListenableKey#key
 *     field.
 */
goog.events.ListenableKey.reserveKey = function() {
  return ++goog.events.ListenableKey.counter_;
};

produces

  interface ListenableKey {
    static reserveKey ( ) : number ;
  }

but TS doesn't allow static method declarations on an interface

Support goog.inherits

/**
 * This creates a TwoThumbSlider object.
 * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
 * @constructor
 * @extends {goog.ui.SliderBase}
 */
goog.ui.TwoThumbSlider = function(opt_domHelper) {
  goog.ui.SliderBase.call(this, opt_domHelper);
};
goog.inherits(goog.ui.TwoThumbSlider, goog.ui.SliderBase);
goog.tagUnsealableClass(goog.ui.TwoThumbSlider);

results in a class definition for TwoThumbSlider without the decorate method that comes from SliderBase.

Duplicate declarations

goog.provide("goog.fx.dom");
goog.provide("goog.fx.dom.ColorTransform");

/** @type {number} */
goog.fx.dom.a = 1;

/** @constructor */
goog.fx.dom.ColorTransform = function() {}

we visit the ColorTransform symbol twice: once for the first provide (which is non-default so we traverse all the symbols) and again for the second provide, where it is the default.

Type 'Object' is not generic

We are writing eg var VOID_TAGS_ : Object < string , boolean > ;
but this is not valid TS.

Could be var VOID_TAGS_ : { [s: string]: string; }; instead

Extending lib.d.ts classes like Error is broken when name is aliased

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
goog.debug.Error = function(opt_msg) {...}

outputs

declare namespace ಠ_ಠ.cl2dts_internal.goog.debug { 
  class Error extends Error { ... }
}

which makes TS sad.

Get parameter types from superclass

listenable.js

/**
 * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
 *     listeners to fire.
 * @param {boolean} capture The capture mode of the listeners to fire.
 * @param {EVENTOBJ} eventObject The event object to fire.
 * @return {boolean} Whether all listeners succeeded without
 *     attempting to prevent default behavior. If any listener returns
 *     false or called goog.events.Event#preventDefault, this returns
 *     false.
 * @template EVENTOBJ
 */
goog.events.Listenable.prototype.fireListeners;

eventtarget.js

/*
 * @implements {goog.events.Listenable}
 */
goog.events.EventTarget = function() {}

/** @override */
goog.events.EventTarget.prototype.fireListeners = function(
    type, capture, eventObject) {
}

.d.ts:

 class EventTarget implements ಠ_ಠ.cl2dts_internal.Unknown {
    fireListeners (a : any , b : any , c : any ) : any ;

Instead we should know the types from the interface being implemented.

Producing constructor with return type

this input

goog.provide('a');

/**
 * @constructor
 */
a.One = function() {};
a.One.prototype.foo = function(x) {};

/**
 * @constructor
 * @extends {a.One}
 */
a.Two = function() {};

goog.inherits(a.Two, a.One);

produces a class Two which has an explicit constructor. We have a return type on the result which is invalid syntax.

declare module 'goog:a' {
  export class One {
    foo (a : any ) : void ;
  }
  export function foo (a : any ) : void ;
  export class Two {
    constructor ( ...a : any [] ) : any ;
    static superClass_ : Object ;
  }
}

AST is changed by closurePass

running on base/string/string.js produces

declare module 'goog:goog.string.Unicode' {
  type goog.string.Unicode = string ;
  export var goog.string.Unicode : {
    NBSP : goog.string.Unicode ,
  };
}

Include supertypes

eg. from javascript/closure/ui/zippy.js

 * @extends {goog.events.EventTarget}

should produce a class goog.ui.Zippy that inherits from EventTarget

top-level functions pick up a `tempCtor` superclass

The following simple definitions transpile to classes that extend tempCtor.

/**
 * To assert to the compiler that an operation is needed when it would
 * otherwise be stripped. For example:
 * <code>
 *     // Force a layout
 *     goog.reflect.sinkValue(dialog.offsetHeight);
 * </code>
 * @type {!Function}
 */
goog.reflect.sinkValue = function(x) {
  goog.reflect.sinkValue[' '](x);
  return x;
};

and

/**
 * @type {!Function}
 * @throws {Error} when invoked to indicate the method should be overridden.
 */
goog.abstractMethod = function() {
  throw Error('unimplemented abstract method');
};

outputs

class sinkValue extends tempCtor 

@typedef with union type

/**
 * A message value that can be handled by a Logger.
 *
 * Functions are treated like callbacks, but are only called when the event's
 * log level is enabled. This is useful for logging messages that are expensive
 * to construct.
 *
 * @typedef {string|function(): string}
 */
goog.debug.Loggable;

/**
 * Logs a message. If the logger is currently enabled for the
 * given message level then the given message is forwarded to all the
 * registered output Handler objects.
 * @param {goog.log.Logger} logger
 * @param {goog.log.Level} level One of the level identifiers.
 * @param {goog.debug.Loggable} msg The message to log.
 * @param {Error|Object=} opt_exception An exception associated with the
 *     message.
 */
goog.log.log = function(logger, level, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.log(level, msg, opt_exception);
  }
};

emits a bad syntax ( )

function log (logger : goog.debug.Logger , level : goog.debug.Logger.Level , msg : ( string | ( ) => string ) , opt_exception ? : Object ) : void ;

@const with no other type info

* @const
 * @private
 */
goog.userAgent.isVersionOrHigherCache_ = {};

emits a literal null (or fails with NPE with error-checking)

Switch to AbstractCommandLineRunner

We currently use CommandLineRunner.getDefaultExterns which gives us problems when we import code into google.
After the next release of closure compiler we can pick up my change, we should instead do
AbstractCommandLineRunner.getBuiltinExterns(opts.getCompilerOptions())

Handle @dict

 * @const
 * @dict
 * @private
 */
goog.events.onStringMap_ = {};

produces

var onStringMap_ : null ;

`goog.require` overloading cannot create an alias for a type

With require overloading on strings, we can emulate:

var MyClass = goog.require('MyClass');

However this does not create a type alias for MyClass so the user cannot write:

var c: MyClass = new MyClass();

even though they can do

var c = new MyClass();

or even add their own type alias with type MyClass = typeof MyClass.prototype.

//cc @mhegazy

Support goog.forwardDeclare

closure/events/events.js:

goog.forwardDeclare('goog.debug.ErrorHandler');
/**
 * Installs exception protection for the browser event entry point using the
 * given error handler.
 *
 * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
 *     protect the entry point.
 */
goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
  goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
      goog.events.handleBrowserEvent_);
};

produces

  function protectBrowserEventEntryPoint (errorHandler : ( ) ) : void ;

Generics in implemented interfaces are not output

The following:

 * @implements {goog.Thenable<TYPE>}
 * @template TYPE,RESOLVER_CONTEXT
 */
goog.Promise = function(resolver, opt_context) {...}

outputs

class Promise < TYPE , RESOLVER_CONTEXT > implements Thenable {

But it should be Thenable<TYPE>.

generic type param missing from signature

* @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function
 *     or object that has a handleEvent method.
 * @param {number=} opt_delay Milliseconds to wait; default is 0.
 * @param {SCOPE=} opt_handler Object in whose scope to call the listener.
 * @return {number} A handle to the timer ID.
 * @template SCOPE
 */
goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
static callOnce < SCOPE > (listener : ( ( ) => any | { handleEvent : ( ) => any } ) , opt_delay ? : number , opt_handler ? : ( ) ) : number ;

the type of opt_handler is ( ) which is not valid

Unstable iteration order

When running tests on OSX with JDK8, the order of declarations in the .d.ts files differs from the golden files.

add support for type aliases

in closure

/**
 * @typedef {A}
 */
goog.namespace.foo;

should output

declare namespace internal.goog.namespace {
  type foo = A;
}
...

Duplicate variables in high-level namespace

Get lots of Duplicate identifier still.

/javascript/closure/ui/ac/ac.jslib.d.ts:3202:NaN: Duplicate identifier 'fx'.
/javascript/closure/ui/ac/ac.jslib.d.ts:3220:NaN: Duplicate identifier 'fx'.

Handle multiple inputs with dependencies

When multiple files are presented, and one of them goog.require's a symbol that is goog.provide'd by another, we should

  • write one .d.ts file for each js_library input
  • use our global internal namespace to reference symbols from the other file.

support generic methods

/**
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
 * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
 *     method.
 * @param {boolean=} opt_useCapture Whether to fire in capture phase
 *     (defaults to false).
 * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
 *     listener.
 * @return {goog.events.ListenableKey} Unique key for the listener.
 * @template SCOPE,EVENTOBJ
 */
goog.events.Listenable.prototype.listen;

produces

listen (a : ( string | EventId < EVENTOBJ > ) , b : (a : EVENTOBJ ) => boolean , c ? : boolean , d ? : ( ) ) : goog.events.ListenableKey ;

but the EVENTOBJ template parameter was undeclared

writing spread args without array type

/**
 * Creates the composition of the functions passed in.
 * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
 * @param {function(...?):T} fn The final function.
 * @param {...Function} var_args A list of functions.
 * @return {function(...?):T} The composition of all inputs.
 * @template T
 */
goog.functions.compose = function(fn, var_args) {}

function compose < T > (fn : ( ...a : any [] ) => T , ...var_args : ( ...a : any [] ) => any [] ) : ( ...a : any [] ) => T ;

error:
/ac.jslib.d.ts:194:NaN: A rest parameter must be of an array type.

Emitting type alias with dotted name

like

declare namespace ಠ_ಠ.cl2dts_internal.goog.dom {
  type goog.dom.TagName = string ;
  var goog.dom.TagName : {

types can't have dotted names

Allow function types

eg

/** @type {function(?):?|{handleEvent:function(?):?}|null} handler */
types.g = null;

Try to preserve parameter names

It's going to be really confusing for developers to see different parameter names (a,b,c...) in the type definitions than were declared. It loses the documentation benefit of seeing the names of the parameters in an API you're trying to call. We should preserve them where possible. (only function literals in typescript require manufacturing names for the parameter types)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.