BeyondCodeBootcamp / js-with-types-jsdoc-tsc-starter

A simple, but non-trivial example of getting the most from JSDoc + tsserver (Type Linting without TypeScript)
Mozilla Public License 2.0
17 stars 1 forks source link

Bug in `tsc`: can't export package-scope types #8

Open coolaj86 opened 2 years ago

coolaj86 commented 2 years ago

You can either have types scoped to the level of the package, or you can export them, but you can't do both:

See

⚠️ Workaround

You can import your own exported types.

in package "foo"

// types.js
/**
 * @typedef {Object} Foo
 * @prop {String} name
 */
// index.js
/** @typedef {import('./types.js').Foo} Foo */

/** @type {Foo} */
let foo;

in package "bar"

/** @type {import('foo/types.js').Foo} */
let foo;

Perfect Solution: Re-export with types

Make index.js be a re-export with all of the local types, then generate the local types.js:

package.json:

{
  "main": "index.js", // our types + package re-export
  "files": [
    "foo.js",
    "types.js"
  ]
}
npm pkg set scripts.prepublish="./bin/re-export-types"

index.js:

module.exports = require('./');

/**
 * @typedef {Object} Bar
 * @prop {Number} age
 */

/**
 * @typedef {Object} Foo
 * @prop {String} name
 */

Generate types.js

./bin/re-export-types:

#!/bin/sh

my_typedefs="$(
    grep typedef ./index.js | cut -d ' ' -f5
)"

rm -f ./types.js
{
    echo '// auto-generated with ./bin/re-export-types'
    echo '// DO NOT EDIT'
    echo ''
    echo '/**'
    for my_type in $my_typedefs; do
        echo " * @typedef {import('./').${my_type}} ${my_type}"
    done
    echo ' */'
} >> ./types.js
/**
 * @typedef {import('./').Foo} Foo
 * @typedef {import('./').Bar} Bar
 */
coolaj86 commented 1 year ago

Fixed with npx jswt reexport