futurgh / ts-to-jsdoc Goto Github PK
View Code? Open in Web Editor NEWTranspile TypeScript code to fully compatible JavaScript + JSDoc comments.
License: MIT License
Transpile TypeScript code to fully compatible JavaScript + JSDoc comments.
License: MIT License
when trying to run the command i get dozens of javascript errors, most of them telling that the property?. notation is invalid, so i'm spending all my time now to fix those javascript errors.
/var/Discord/gcomponents/node_modules/.bin/ts-to-jsdoc: 1: use strict: not found
: not foundd/gcomponents/node_modules/.bin/ts-to-jsdoc: 1:
/var/Discord/gcomponents/node_modules/.bin/ts-to-jsdoc: 2: Syntax error: "(" unexpected
System: Windows Linux Subsystem Ubuntu
Type info of parameters of arrow functions are stripped.
type Video = {
id: string;
// more fields
};
type Playlist = {
videos: Video[];
};
const fetchPlaylist = async (
playlistId: string,
): Promise<Playlist> => {
// some code
};
will just be converted to
const fetchPlaylist = async (playlistId) => { /* code */}
However, if refactor fetchPlaylist to async function fetchPlaylist()
,
ts-to-jsdoc will convert type infos to JSDoc successfully.
First off, this is incredible. Thank you so much for the hard work put into this!
I have made a quick browser prototype that allows users to generate the types in the browser. https://smacpherson64.github.io/typescript-to-jsdoc/
I would love to use ts-to-jsdoc
directly, but had to make two adjustments to get it to work in the browser:
useInMemoryFileSystem: true
to the projectWould you be open to a PR to add a browser based version alongside the node one?
When try to use it, it does not output anything
OS: Windows 11
Node: 20.16.0
NPM: 10.8.1
Steps to reproduce:
Expected result:
get vanilla js files
Actual result:
no output
Hey again,
I have a few projects that use namespaces in JSDoc. Are you open to the idea of generating namespaces in JSDoc?
For example:
/** Namespace description */
export namespace Example {
/** Type description */
export type SubType = {
/** Property description */
name: string
}
/** Interface description */
export interface SubInterface {
/** Property description */
label: string;
}
}
would become:
/**
* Namespace description
* @namespace Example
*/
/**
* Type description
* @typedef {Object} Example.SubType
* @property {string} name Property description
*/
/**
* Interface description
* @typedef {Object} Example.SubInterface
* @property {string} label Property description
*/
Type definition are not keeped for exported variable, for example:
export const type: string = null;
/**
* Size.
*/
export let size: "small"|"medium" = null;
should be transpiled to :
/** @type {string} */
export const type = null;
/**
* Size.
* @type {"small"|"medium"}
*/
export let size = null;
Context: I'm trying to integrate this lib to transpile a svelte component!
Version: 1.2.0
I have multiple interfaces and functions to export from one file.
As I do that I find that the generated .js file has lines that contain invalid comma _betweeen two @typedef
s.
A minimal example:
Input: tests.ts
export interface One {
foo1: string;
bar1: string;
baz1: number;
}
export interface Two {
foo2: string;
bar2: string;
baz2: string;
}
export function test(one: One, two: Two) {
console.log(
one.foo1 + two.foo2,
one.bar1 + two.bar2,
one.baz1 + two.baz2
);
}
Use these commands to generate a test.js
output file:
#!/bin/bash
CURDIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
INPUT_FILE="$CURDIR/test.ts"
OUTPUT_DIR="$CURDIR/output"
npx ts-to-jsdoc -f "$INPUT_FILE" -o "$OUTPUT_DIR"
What I got as output:
Output: test.js
/** @param {One} one
* @param {Two} two
* @returns {void}
*/
export function test(one, two) {
console.log(one.foo1 + two.foo2, one.bar1 + two.bar2, one.baz1 + two.baz2);
}
/** @typedef {Object} One
* @property {string} foo1
* @property {string} bar1
* @property {number} baz1
*/,/** @typedef {Object} Two
* @property {string} foo2
* @property {string} bar2
* @property {string} baz2
*/
You can see that between the two @typedef
s, a weird comma shows up, which is invalid JavaScript syntax.
Just wanted to thank you, i can now say fuck to any anti-typescript people without problems and really quickly. Ima write an article on that ahahah
Hi,
this is a very useful project!
Unfortunately type predicates are not converted correctly. They are just converted to @return {boolean}
.
Would this be inside the purpose of ts-to-jsdoc
?
Thank you!
It would be nice to do one off ts to jsdoc conversions, can you provide an example on how to do this via the command line
I was hoping for something lie
npx ts-to-jsdoc filename.ts
Hey There 👋
I've seen @smacpherson64 created an online playground at typescript-to-jsdoc and it really helps understanding what the library does, and allows us the check out what the generated jsdoc looks like.
What do you think about linking it in the README, or directly adding it to the repo (if @smacpherson64 is okay with it)? It could be even used later for bug reproductions by adding a code sharing functionality to it, like what https://www.typescriptlang.org/play/ has.
I checked out https://github.com/silverbulletmd/silverbullet at version 0034b4e8a7d2efd90ac1056a145865725f869b56
and ran:
silverbullet> ts-to-jsdoc.cmd .\common\
ManipulationError: Manipulation error: A syntax error was inserted.
manifest.ts-to-jsdoc.ts:73:2 - error TS1109: Expression expected.
73 * syntax?: { [key: string]: NodeDef };
... and more error output
I imagine this could be newer TypeScript. silverbullet uses deno which uses typescript 5.2.2 in latest version while ts-to-jsdoc
seems to use ^4.9.4
When defining a type using generics, the generic variables need a typedef. Other
typescript source:
export type NeverType<T, Type> = T extends Type ? never : T;
javascript input:
/** @typedef {T extends Type ? never : T} NeverType */ // No typedef for T or Type causes an error when generate ts from js
typescript definition re-generated (using allowJs) to .d.ts
export type NeverType = T extends Type ? never : T;
Adding the following to the javascript output solves the error (there may be other ways, not a JSDoc expert)
/** @typedef {any} T */
/** @typedef {any} Type */
Given TS code:
class Frame {
bias: number;
constructor() {
this.bias = 0.001;
}
}
class Multiframe extends Frame {
bias: number;
}
const frame = new Frame();
const multiframe = new Multiframe();
console.log('frame.bias', frame.bias);
console.log('multiframe.bias', multiframe.bias);
And tsc
compiles into this JS:
"use strict";
class Frame {
constructor() {
this.bias = 0.001;
}
}
class Multiframe extends Frame {
}
const frame = new Frame();
const multiframe = new Multiframe();
console.log('frame.bias', frame.bias);
console.log('multiframe.bias', multiframe.bias);
Output:
However, ts-to-jsdoc
transpiles into:
class Frame {
bias = undefined;
constructor() {
this.bias = 0.001;
}
}
/** @extends Frame */
class Multiframe extends Frame {
bias = undefined;
}
const frame = new Frame();
const multiframe = new Multiframe();
console.log('frame.bias', frame.bias);
console.log('multiframe.bias', multiframe.bias);
Output:
Not a showstopper, but would be helpful for new users.
Use case: I was generating .js file from a single .ts file. It failed with an ambiguous error. The file had imports, and I presumed that was the issue. The directory was self-containing i.e. .ts in this directory only imported from themselves or from node. So I used the directory option and that worked.
Fix suggested:
typescript input
import { SomeThing } from './some-dir';
actual javascript output: in ESM, this throws ERR_UNSUPPORTED_DIR_IMPORT
import { SomeThing } from './some-dir';
expected javascript output: resolve directory import to file import
import { SomeThing } from './some-dir/index.js';
in commonjs, the directory import would work
const { SomeThing } = require ('./some-dir');
ideally, ts-to-jsdoc would support converting an input directory, so it can resolve file paths
related issues
possible solutions
resolveFullPaths
option of tsc-alias{ module: "nodenext" }
to compilerOptions to generate ESM javascript, then typescript requires file import and throws error TS2834: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Consider adding an extension to the import path.
tsc-esm-fix --target='target/es6'
tsc-esm-fix --src='src/main/ts' --ext='.js'
Allow to use Javascript files as input, filling JsDoc comments with types inferred from their dependencies. I'm not worried too much about having a lot of any
types as far as it generates the JsDoc comments with all parameters and return type, so later I can keep improving them by hand. If possible, do it replacing the actual files in place. Is that possible? Does it falls on scope of this project? If not, is there any one that can do this? I would not like to move to Typescript just for typing, and creating all the JsDoc comments by hand is tyring...
input
function f({
a,
b,
}: {
a: string,
b: number,
}, arg2: string) {
return a + arg2
}
actual
/**
* @param {{
* a: string,
* b: number,
* }} {
* a,
* b,
* }
* @param {string} arg2
* @returns {string}
*/
function f({ a, b, }, arg2) {
return a + arg2;
}
expected: remove the { a, b }
/**
* @param {{
* a: string,
* b: number,
* }}
* @param {string} arg2
* @returns {string}
*/
function f({ a, b, }, arg2) {
return a + arg2;
}
javascript has only positional arguments (compared to python's kwargs)
so it's safe to skip the variable name if its too complex
Nice project!
Is there any way of making it use relative paths instead of absolute ones for imported types when using the project option? Absolute paths makes a project mostly unable to collaborate to together with others with different setups.
There doesn't seem to be any disadvantage in using e.g.
@returns {import("./file").File}
over
@returns {import("C:/path/to/file").File}
typedefs were properly generated from a source file. Another .ts source refers to those types, and to make it work I had to add typedefs to import those in the target .js
For example:
/**
i have a similar script to remove typescript types, and generate pretty javascript
https://github.com/milahu/random/blob/master/javascript/tsx2jsx.mjs
that script will run 2 loops
inspect the transform: git diff HEAD^
revert the transform: git reset --hard HEAD~2
this could be hidden behind a flag like ts-to-jsdoc --git
The ts-to-jsdoc complier (as of v2.0.0) does not seem to generate jsdoc type annotations for constructors, getters or setters. In this (contrived, for the purpose of demonstration) example I would expect type annotations for the constructor and the getters and setters but none are generated:
input:
/**
represents a point in 2d space
*/
class Point {
#x: number
y: number
/** creates a new point */
constructor(x: number,y: number) {
this.x = x
this.y = y
}
/** adds another point to this one and returns the result */
add(p : Point) : Point {
return new Point(this.x + p.x, this.y + p.y)
}
/** gets the value of X */
get x(): number {
return this.#x
}
/** sets the value of x */
set x(arg: number) {
this.#x = arg
}
}
I would expect the output to contain jsdoc @param for the getter, setter and constructor, but it only has it for the add method, with the type information for the getters and setters just stripped:
/**
represents a point in 2d space
*/
class Point {
#x;
y;
/** creates a new point */
constructor(x, y) {
this.x = x;
this.y = y;
}
/**
* adds another point to this one and returns the result
* @param {Point} p
* @returns {Point}
*/
add(p) {
return new Point(this.x + p.x, this.y + p.y);
}
/** gets the value of X */
get x() {
return this.#x;
}
/** sets the value of x */
set x(arg) {
this.#x = arg;
}
}
typescript input
export interface SomeType {
someKey: string;
}
export function someFunction(someString: string): SomeType {
return { someKey: someString };
}
actual javascript output
/** @param {string} someString
* @returns {import("/absolute/path/to/workdir/input-file-basename.ts-to-jsdoc").SomeType}
*/
export function someFunction(someString) {
return { someKey: someString };
}
/** @typedef {Object} SomeType
* @property {string} someKey
*/
expected jsdoc comment: no type import
/** @param {string} someString
* @returns {SomeType}
*/
I assume this tool can't do this, but I'm wondering if you might know how to go about it.
For instance, I'm looking at a repo that has each .js
file documented with a .d.ts
file, which I'd like to merge.
the \r\n
line ends break the binary on linux
this only appears when i install with yarn (yarn@1)
cd $(mktemp -d)
yarn init -y
yarn add ts-to-jsdoc
jq -r .version node_modules/ts-to-jsdoc/package.json
# 1.1.2
npx ts-to-jsdoc
# /usr/bin/env: ‘node\r’: No such file or directory
# /usr/bin/env: use -[v]S to pass options in shebang lines
hexdump -C node_modules/.bin/ts-to-jsdoc | head -n2
# 00000000 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 6e |#!/usr/bin/env n|
# 00000010 6f 64 65 0d 0a 22 75 73 65 20 73 74 72 69 63 74 |ode.."use strict|
printf '\r\n' | hexdump -C
# 00000000 0d 0a |..|
# 00000002
wget https://registry.yarnpkg.com/ts-to-jsdoc/-/ts-to-jsdoc-1.1.2.tgz
tar xf ts-to-jsdoc-1.1.2.tgz
hexdump -C package/bin/ts-to-jsdoc | head -n2
# 00000000 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 6e |#!/usr/bin/env n|
# 00000010 6f 64 65 0d 0a 22 75 73 65 20 73 74 72 69 63 74 |ode.."use strict|
wget https://registry.npmjs.com/ts-to-jsdoc/-/ts-to-jsdoc-1.1.2.tgz
# same
workaround
node node_modules/.bin/ts-to-jsdoc
the \r
is not in the source code,
so i guess you edited the bin/ts-to-jsdoc
file manually before publish
fix: add a build script tsc --build
which runs on npm publish
next error
npx ts-to-jsdoc -o src-jsdoc src/
# Error: Cannot find module '../index'
fix
sed -i 's,"../index","ts-to-jsdoc/index.js",' node_modules/.bin/ts-to-jsdoc
next error
npx ts-to-jsdoc -o src-jsdoc/ src/
# [ERROR] Output directory /tmp/src-jsdoc does not exist.
workaround
mkdir src-jsdoc
Test code:
import React from 'react';
import { InfoBox } from 'pcui';
import { ObserverData } from '../types';
// InfoBox that shows an error
const ErrorBox = (props: { observerData: ObserverData }) => {
return <InfoBox class="pcui-error" title='Error' hidden={!props.observerData.ui.error} text={props.observerData.ui.error} icon='E218'/>;
};
export default ErrorBox;
Output:
// InfoBox that shows an error
/**
* @param {{ observerData: ObserverData }} props
* @returns {InfoBox}
* @type {{ props: any; "": any; }}
*/
const ErrorBox = (props) => {
return class {
};
"pcui-error";
title = 'Error';
hidden = {};
props.observerData.ui.error;
}, text = { props, : .observerData.ui.error }, icon = 'E218' / > ;
;
export default ErrorBox;
The output in jsdoc has not the type import.
desired file "example.ts":
import { ParamType } from "./example2";
function someFunction(param: ParamType) {}
file "example2.ts" where the type is located:
export type ParamType = string;
Output JS:
/**
* @param {ParamType} param
* @returns {void}
*/
function someFunction(param) { }
export {};
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.