neon icon indicating copy to clipboard operation
neon copied to clipboard

Generate TypeScript definition files

Open darkwater opened this issue 7 years ago • 17 comments

It'd be very useful if neon could generate a TypeScript definition file (foo.d.ts) based on the functions (and possibly "interfaces") that are exported.

Since the parameters in TypeScript aren't actually parameters to the original Rust function, I'm experimenting with a #[jsfun()] attribute:

declare_types! {
    pub class JsDbConn for DbConn {
        #[jsfun()]
        init(_cx) {
            ...
        }

        #[jsfun(): Array<Library>]
        method getLibraries(mut cx) {
            ...
        }
    }
}

and a build.rs which extracts these and writes to an index.d.ts file.

In my own project I also define a couple of "types" which are essentially structs "exported" as interfaces in the definitions file.

darkwater avatar Aug 01 '18 19:08 darkwater

Attributes have more defined syntax than I expected, so I'm now trying out doc comments instead, like this:

pub class JsDbConn for DbConn {
    /// Connect to the database. Multiple connections can co-exist.
    ///
    /// constructor()
    init(_cx) {
        ...
    }

    /// Fetch all Libraries from the database.
    ///
    /// getLibraries(): Array<Library>
    method getLibraries(mut cx) {
        ...
    }
}

This means we can also add documentation to the definition files, I think that'll look like this:

export class DbConn {
    /*~ Connect to the database. Multiple connections can co-exist.
     */
    constructor();

    /*~ Fetch all Libraries from the database.
     */
    getLibraries(): Array<Library>;
}

I'll post my code when I got everything working, but I think it might be better to rewrite it from the ground up for Neon as this is my first time parsing Rust code and I don't think I used syn properly.

darkwater avatar Aug 03 '18 01:08 darkwater

Alright, I got it working for my project now. Here's what I got. I'll document it tomorrow as it's getting late here but I really think it's best to just rewrite proper code from scratch. But if anyone else wants this functionality right now, you should be able to just dump this in your build.rs and have it just work.

darkwater avatar Aug 03 '18 02:08 darkwater

@darkwater Your link is 404, could you paste the code in a gist?

amaury1093 avatar Apr 06 '19 08:04 amaury1093

Wouldn't some cooperation with (or "inspiration by") https://github.com/rustwasm/wasm-bindgen be usefull since they also generate typescript defs & I'd suppose that it's in a pretty mature state.

kubijo avatar May 11 '20 12:05 kubijo

@kubijo agreed! I just thought the same thing but you were faster 🚀

anyway, https://github.com/rustwasm/wasm-bindgen/tree/master/crates/backend seems to be a good start~

three-star-flex-book avatar May 18 '20 14:05 three-star-flex-book

has there been any progress in this?

Figments avatar Aug 25 '20 17:08 Figments

@Figments Not on this specifically—in time, the current class macro will probably be deprecated in favour of some other solution. At first, a lower-level primitive JsBox to safely pass Rust structs to JavaScript, and later possibly a proc macro like in node-bindgen. With a proc macro, we could definitely generate typings. I think it's hard to achieve in the current class macro. macro_rules! is not that powerful.

goto-bus-stop avatar Sep 04 '20 14:09 goto-bus-stop

Anything I can do to help?

skewballfox avatar Oct 28 '20 17:10 skewballfox

Anything new?

TheBotlyNoob avatar Mar 16 '22 22:03 TheBotlyNoob

@TheBotlyNoob This would be a great feature, but unfortunately it's not something than anyone has been able to work on.

kjvalencik avatar Mar 16 '22 22:03 kjvalencik

sad... thanks for the answer.

TheBotlyNoob avatar Mar 16 '22 22:03 TheBotlyNoob

This is the main feature I was hoping for when considering a move from node-addon-api to neon. Is anyone working on this and looking for help?

thegecko avatar Apr 25 '22 14:04 thegecko

@thegecko https://napi.rs/ has already supported this feature

Brooooooklyn avatar Apr 26 '22 04:04 Brooooooklyn

Any updates here? Thanks!

elichai avatar Sep 29 '22 13:09 elichai

I think this would be difficult at best or impossible at worst to implement because of the very dynamic nature of neon's API

meadowsys avatar Oct 15 '22 18:10 meadowsys

Something like this would require proc macros and static function signatures. However, Neon has avoided these because of the amount of code they would need to inject.

However, GAT recently landed which could allow a trait based approach on tuple arguments to work. The prac macro could be limited to outputting the types and very light signature rewriting (zero code injection).

Something like:

#[neon]
fn greet(mut cx: FunctionContext, name: JsString, count: JsNumber) -> JsResult<JsString> {
    todo!()
}

// transforms into

fn greet(mut cx: FunctionContext, (name, count): (Handle<JsString>, Handle<JsNumber>) -> JsResult<JsString> {
    todo!()
}

This is a straightforward transform. No magic. However, this is only part of the puzzle. We have a function type definition, but we still need the type for the exports, modules, callbacks and a lot more.

kjvalencik avatar Oct 15 '22 19:10 kjvalencik