Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Is anyone else using javascript + jsdoc + .d.ts files, and using typescript as a kind of linter?

I'm really enjoying this setup, I get to use tools that work on JS source code without sticking them in a build typeline. I find it easier to read as well - the function declarations are nice and short as all the type annotations are in a comment above. Also one less transpilation step.



Yes this has been a lifesaver. We have a nodejs application without a lot of obvious structure and lots of ad-hoc objects thrown around. Gradually adding .d.ts files, adding tsdoc comments (`@param {SomeType} foo`), and running `tsc` at test-time has already caught numerous bugs that otherwise would have required lots of unpleasant time with the debugger.

We just mandated that all new code get written in typescript (we transitioned everything to run via `ts-node` before actually using any typescript and it was super painless). Any "significant" changes to existing code (>= 10 lines diff usually) must either first convert the code to TS or add types via tsdoc. This is a "first step" PR that lets us confidently make changes in subsequent PRs after type info is there to help. Forces us to pay down tech-debt in a real way that has immediate payback.


I do this, too -- sort of. I prefer for type-checking to give useful feedback than for it to act as a control-gate, because the latter increases the length of the feedback loop between writing code and seeing its behaviour.

Rather than having the TypeScript compiler not even transpile code into JavaScript unless it perfectly passes type-checking, I use Babel to transpile and run the TypeScript type-checker separately (with the `--noEmit` flag).


Yes - Lighthouse does this https://github.com/GoogleChrome/lighthouse

Chrome DevTools uses Closure compiler directly, but also via jsdoc. In fact, the TS team uses chrome devtools as a test case to validate their jsdoc interop: https://github.com/microsoft/TypeScript/tree/master/tests/ca...



I do this extensively with Flow comment syntax at work and it's great. I tried it w/ Typescript on a side project recently, but I found it to be a bit limited (e.g. @callback doesn't play well with RORO pattern) and the syntax is a bit clunky.

But having runnable code without a build step is definitely a very big plus for me.


I never use the callback tag, I tend to just do:

  /** @param {(x: X) => Y} f */
Works fine. If you can let me know a RORO pattern you had trouble typing I might be able to help.


The problem with @param is that it requires a binding name

I ended up doing this instead:

    /**
    @typedef {{x: string}} FooArgs
    @typedef {{y: string}} FooResult
    @type {function(FooArgs): FooResult}
    */
    export const foo = ({x}) => ({y: x});
It works, but the double curly feels a bit clunky. Compare to Flow:

    /*::
    type FooArgs = {x: string};
    type FooResult = {y: string};
    type Foo = (FooArgs) => FooResult;
    */
    export const foo /*: Foo */ = ({x}) => ({y: x});
In Flow, the declaration ends up looking essentially the same between comment syntax and non-comment syntax.

With TS, RORO ends up looking like Flow (but with weirder indentation on large enough structs), whereas I'd prefer to express regular functions in terms of @callback, @param and @returns since that's more in line w/ the spirit of jsdoc. Not a huge deal, in any case, considering the upsides of comment syntax.


index.d.ts:

    type FooArgs = {x: string}
    type FooResult = {y: string}
    type Foo = (_: FooArgs) => FooResult
index.js:

    /// <reference path="index.d.ts"/>
    /** @type {Foo} */
    export const foo = ({x}) => ({y: x})
Works as well


Good point!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: