1

Closed

declarations cannot describe function 'try' on module

description

I'm modelling a declaration .d.ts file for library that exports a method try on a named module:
declare module Promise {
    function try():Promise {
        // ...
    }
}
AFAIC try is a acceptable keyword in ES5, but I get this error report:
bluebird/bluebird.d.ts(385,14): error TS1006: Identifier expected; 'try' is a keyword.
bluebird/bluebird.d.ts(385,17): error TS1005: '{' expected.
bluebird/bluebird.d.ts(385,23): error TS1005: ')' expected.
bluebird/bluebird.d.ts(385,41): error TS1003: Identifier expected.
bluebird/bluebird.d.ts(385,48): error TS1003: Identifier expected.
bluebird/bluebird.d.ts(385,53): error TS1003: Identifier expected.
bluebird/bluebird.d.ts(385,60): error TS1003: Identifier expected.
bluebird/bluebird.d.ts(385,64): error TS1005: ';' expected.
bluebird/bluebird.d.ts(385,65): error TS1008: Unexpected token; 'module, class, interface, enum, import or statement' expected.
bluebird/bluebird.d.ts(385,76): error TS1003: Identifier expected.
My compiler string is:
tsc "defs/bluebird/bluebird-tests.ts" --sourcemap --target ES5 --module commonjs --out defs/bluebird/bluebird-tests.js
This is in typescript v0.9.5 under grunt-ts.
Closed Jul 28, 2014 at 11:18 PM by jonturner
As part of our move to GitHub, we're closing our CodePlex suggestions and asking that people move them to the GitHub issue tracker for further discussion. Some feature requests may already be active on GitHub, so please make sure to look for an existing issue before filing a new one.

You can find our GitHub issue tracker here:
https://github.com/microsoft/typeScript/issues

comments

danquirk wrote Feb 20, 2014 at 1:58 AM

As the error suggests, try is a keyword not an identifier and it can't be used in this position. If you try to define a function like this in JavaScript you'll also get an error:
function try() {}
SyntaxError: Unexpected token try
** Closed by danquirk 02/19/2014 5:58PM

Bartvds wrote Feb 20, 2014 at 3:49 AM

Not as a loose function, but you can use it as a method (= callable property) in ES5:

I'm modelling this library: https://github.com/petkaantonov/bluebird

It definitely has a try method: https://github.com/petkaantonov/bluebird/blob/master/API.md
function Promise() {

}
Promise.try = function () {

};

Bartvds wrote Feb 21, 2014 at 9:56 PM

@danquirk please re-open this issue:

Here is the example from the Bluebird API I linked before:

We need to model this: Promise.try():
function getUserById(id) {
    return Promise.try(function(){
        if (typeof id !== "number") {
            throw new Error("id must be a number");
        }
        return db.getUserById(id);
    });
}

Bartvds wrote Feb 25, 2014 at 4:30 AM

This doesn't work in devel branch (1.0.0):

https://github.com/borisyankov/DefinitelyTyped/blob/b76db08d5046efe57a94f01897313ec4d1c910d5/bluebird/bluebird-tests.ts#L493-L515

https://github.com/borisyankov/DefinitelyTyped/blob/b76db08d5046efe57a94f01897313ec4d1c910d5/bluebird/bluebird.d.ts#L389-L390

If I enable it the compiler complains that try is a keyword, while it is exported as a property. (I think the declaration works here differently then module code would).

Bartvds wrote Mar 14, 2014 at 2:16 AM

This is a problem: I'm re-opening this issue as declarations currently cannot describe certain modules.

For example: 'try' can be a valid method name: (like in Bluebird)

Minimal source:
// foo-module.js from npm/bower
module.exports = {
    try: function (x) {
        // ..
    }
}
So this is a legal case to declare:
declare module 'foo-module' {
    export function try (x: any): void;
}
Same for throw (in Chai), catch, finally, return etc (used in promise libraries but others too).

I am aware th following implementation is not valid typescript.
export module Foo {
    export function try (x: any): void {
        // ..
    }
}
But this is:
export var foo = {
    try: function (x) {
        // ..
    }
}

danquirk wrote Mar 14, 2014 at 3:11 AM

I see what you mean. The problem is that if we were to allow 'try' in that position we would also be allowing other code patterns that are illegal, essentially putting more burden on the user to make sure they use the right terms in the right places lest their program generate invalid JS. That said, it is possible so I've marked this as a suggestion for the future that we can evaluate.

In the meantime, I think you can model this using a clodule in the .d.ts which isn't quite as clean but does the job. So this:
class Promise {
    static try(x: any): void { }
}

module Promise {
    export var value: any;
}
will generate this .d.ts:
declare class Promise {
    static try(x: any): void;
}
declare module Promise {
    var value: any;
}
and now this works:
/// <reference path='Promises.d.ts'/>

function getUserById(id) {
    return Promise.try(function () { // no error, try shows up in the completion list, has signature help, etc
        if (typeof id !== "number") {
            throw new Error("id must be a number");
        }
        return db.getUserById(id);
    });
}

Bartvds wrote Mar 14, 2014 at 4:23 AM

Thanks, that will cover for now. We had some hacks with interface earlier but it wasn't ideal.

But for later:
.. burden on the user to make sure they use the right terms in the right places lest their program generate invalid JS.
I think if we're declaring a module then the try is a different semantic then when we're actually implementing.

And besides that, is there a other use of the try keyword in a declaration at all? You can't do much statements there.

If the rest of the syntax is valid then these keywords should be acceptable in a declaration situation if it is possible to create/use the construct with valid JavaScript.