Description
π Search Terms
"omit typedef", "exclude typedef"
β Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
β Suggestion
When emitting type declarations from JavaScript sources, the type is already defined in the TypeScript syntax, so there's no need to copy over any @type
, @typedef
, or @template
directives.
Types can also be stripped out of @param
and @returns
directives.
This could be taken further, by deleting JSDoc strings altogether if after stripped the types, they become empty.
π Motivating Example
For example, I have the following files:
css-select-adapter.js
/**
* @param {Map<import('../types.js').XastNode, import('../types.js').XastParent>} parents
* @returns {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']}
*/
export function createAdapter(parents) {
// β¦
}
tsconfig.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"declaration": true,
"emitDeclarationOnly": true,
"outDir": "types/"
},
"include": ["lib/svgo-node.js", "lib/svgo.js"]
}
The emitted type declaration is:
/**
* @param {Map<import('../types.js').XastNode, import('../types.js').XastParent>} parents
* @returns {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']}
*/
export function createAdapter(parents: Map<import("../types.js").XastNode, import("../types.js").XastParent>): Required<import("css-select").Options<import("../types.js").XastNode & {
children?: any;
}, import("../types.js").XastElement>>["adapter"];
But the types defined in the JSDoc become unnecessary since it's already defined in TypeScript, so it should just be:
/**
* @param parents
* @returns
*/
export function createAdapter(parents: Map<import("../types.js").XastNode, import("../types.js").XastParent>): Required<import("css-select").Options<import("../types.js").XastNode & {
children?: any;
}, import("../types.js").XastElement>>["adapter"];
This could be taken further, by removing the @param
, @returns
, and @template
directives if all of them have no value, and removing the JSDoc outright if after removing empty directives the JSDoc becomes empty:
export function createAdapter(parents: Map<import("../types.js").XastNode, import("../types.js").XastParent>): Required<import("css-select").Options<import("../types.js").XastNode & {
children?: any;
}, import("../types.js").XastElement>>["adapter"];
π» Use Cases
In SVGO, we emit type declarations from our JSDocs. However, the type declarations can be quite noisy. It would be valuable if the output was tidied up:
- To make them quicker/easier to human-review when needed.
- Reduce the size of the published npm package.
We currently do not do any workarounds. We just publish the additional content to npm.