-
-
Notifications
You must be signed in to change notification settings - Fork 737
VarArgs inference overly aggressive when checking JavaScript files. #1617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
One additional oddity with the example I provided for the issue that I just noticed. When typedoc generates the documentation, it indicates the method name as |
TypeDoc appears to be doing the right thing here. In the playground, if the language is set to TypeScript, then, yes To set the language to JS, you have to go to the TS Config tab in the playground (weird spot, but...) |
OK, maybe I'm a bit blind, but clicking your link to the TypeScript playground, which has my example, and the
The sample compiles fine, but I don't see anywhere I can view the generated typedoc documentation. I'm attaching my local project which has To run the project:
I also tried this project at home on my Windows 10 laptop with the latest version of nodejs with the same results. I'm limited at work to nodejs v12.22.1 because we are still running Windows 7 Enterprise. |
Sorry, the playground doesn't show TypeDoc output, I was providing that to show that the method is variadic.
This is not true - TypeScript infers this function as having a vararg, so TypeDoc does the same. As the page you linked in the handbook says:
This doesn't say anything about accessing individual indexes, even this function implicitly has varargs. function foo(arg) {
arguments;
} |
However, looking at the AST generated by the playground, goto settings to turn it on, it shows only one parameter for that method. TypeScript may infer
|
The AST represents what you wrote - that function doesn't have a rest argument in the parameters, so the AST won't include it. The AST also won't include inferred types, so there will be no function doIt() {
return 1
} ... even though class Foo<T> {
prop: T extends number ? string : boolean
}
class Bar extends Foo<number> {
// bar.prop should be documented as type `string`, not `T extends number ? string : boolean`
} The const custom = globalThis.Symbol()
namespace Symbol {
export const hasInstance = globalThis.Symbol()
}
class Sym {
[custom]: 1
[Symbol.hasInstance]: () => true
[globalThis.Symbol.hasInstance]: () => false
} |
As far as symbols, would it be possible to allow |
You could do that pretty easily with a plugin: const { Converter, ReflectionKind } = require("typedoc")
exports.load = function(app) {
app.converter.on(Converter.EVENT_CREATE_SIGNATURE, (_, refl) => rename(refl));
app.converter.on(Converter.EVENT_CREATE_DECLARATION, (_, refl) => rename(refl));
}
function rename(refl) {
const name = refl.comment?.getTag("name")?.text.trim();
refl.comment?.removeTags("name")
if (name) {
refl.name = name
if (refl.kindOf(ReflectionKind.SomeSignature)) {
refl.parent.name = refl.name;
}
}
}
|
Wow, I'll have to look into TypeDoc's plugin architecture!! Thanks for the starter code and pointer, much appreciated. |
I realized, coming back to this, that you can also just use a plugin to remove the rest signature if you don't want TypeScript's inference behavior. This will remove any rest parameters of type const { Converter, ReflectionKind } = require("typedoc")
exports.load = function(app) {
app.converter.on(Converter.EVENT_CREATE_SIGNATURE, (_, refl) => {
if (refl.parameters.length === 0) return;
const param = refl.parameters[refl.parameters.length - 1];
if (param.type.toString() === "any[]" && param.flags.isRest) {
refl.project.removeReflection(param)
}
});
} |
I tried to get this working, but typedoc says the plugin could not be loaded:
The file is really there in the directory specified: |
I had a further thought on this. Typedoc should know that it has a Symbol to document, so why not use the Symbol's description and if it's an empty string fall back to the existing strategy. For example, for all well known symbols in JavaScript, their description is the name of the well know symbol: assert( Symbol.iterator.description === 'Symbol.iterator' ) ;
assert( Symbol.hasInstance.description === 'Symbol.hasInstance' ) ; If you follow the existing convention in your own code, then: const custom = globalThis.Symbol( 'Sym.custom' )
namespace Symbol {
export const hasInstance = globalThis.Symbol( 'Symbol.hasInstance' )
}
class Sym {
[custom]: 1
[Symbol.hasInstance]: () => true
[globalThis.Symbol.hasInstance]: () => false
} Typedoc could generate: Thoughts? |
This should have worked, paths starting with
The problem with this is that it conflates runtime values and type values. There is nothing on the type typeof Symbol.iterator["description"] // string, not "Symbol.iterator" |
Success!! OK to get the name plugin to work required a few adjustments, due to my environment, but there also appears to be a subtle bug in typedoc when determining the plugin directory.
Attached is the updated source for the plugin. Works great 😄, thanks again for demonstrator to get my feet wet with typedoc plugins. |
Spoke a little too soon... The
Is there something else that a plugin needs to do to play nice with other plugins? BTW, I'm using these two plugins in different comments. The |
Supported since 14.5 or so, works on my machine ;)
This is because these are different types of options. Plugins might be a npm package - specifying I took a quick look at the mermaid plugin, but don't see any obvious reason it would cause the name plugin to break. (Why does it inherit from the internal ConverterComponent?! There's absolutely no reason to do this...) It might be that it isn't broken, but that it isn't being loaded. When you specify |
Search terms
Expected Behavior
@params
to document the method and not infer an VarArgs.Actual Behavior
When using
arguments
in a JavaScript function, Typedoc infers VarArgs onto the end of the method even when an actual argument has not been used, e.g., usingarguments.length
as opposed to an actual argumentarguments[1]
. This appears to be a Typedoc issue since using the TypeScript playground indicates that the method has only one argument of typeany
as expected and correctly didn't apply VarArgs per this statement in the TypeScript documentation. What appears to be at issue with the documentation generated by Typedoc is that any reference toarguments
will assume themethod/function
has, ...args: any[]
rather than strictly only when an reference to an actual argument is made, e.g.,arguments[1]
.Steps to reproduce the bug
typedoc.json
tsconfig.js
test-class.js
Environment
The text was updated successfully, but these errors were encountered: