Skip to content

Commit dfb5a44

Browse files
committed
Convert explicitly typed fn-variables as variables
Resolves #2881
1 parent 70a0d92 commit dfb5a44

File tree

16 files changed

+124
-40
lines changed

16 files changed

+124
-40
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ title: Changelog
1313
- The `source-order` sort ordering now considers package names / package relative paths instead of using the absolute paths to a file.
1414
- TypeDoc will only check for a project README file next to the discovered `package.json` file if `--readme` is not set
1515
this change improves handling of monorepo setups where some packages have readme files and others do not, #2875.
16+
- Function-like variable declarations with a type annotation will now be converted as variables unless annotated with `@function`, #2881.
1617

1718
### API Breaking Changes
1819

@@ -42,6 +43,7 @@ title: Changelog
4243
- TypeDoc now exports a `typedoc/browser` entrypoint for parsing and using serialized JSON files, #2528.
4344
- Type `packageOptions` as `Partial<TypeDocOptions>`, #2878.
4445
- TypeDoc will now warn if an option which should only be set at the root level is set in `packageOptions`, #2878.
46+
- Introduced `@function` tag to force TypeDoc to convert variable declarations with a type annotation as functions, #2881.
4547

4648
### Bug Fixes
4749

@@ -63,7 +65,7 @@ This will be the last v0.27.x release, see #2868 for discussion on the 0.28 beta
6365

6466
### Features
6567

66-
- Added support for TypeScript 5.8
68+
- Added support for TypeScript 5.8
6769

6870
## v0.27.8 (2025-02-21)
6971

site/tags.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ children:
1616
- tags/example.md
1717
- tags/expand.md
1818
- tags/experimental.md
19+
- tags/function.md
1920
- tags/group.md
2021
- tags/hidden.md
2122
- tags/hideconstructor.md
@@ -150,6 +151,7 @@ as internal for use with
150151
- [`@eventProperty`](./tags/eventProperty.md)
151152
- [`@expand`](./tags/expand.md)
152153
- [`@experimental`](./tags/experimental.md)
154+
- [`@function`](./tags/function.md)
153155
- [`@hidden`](./tags/hidden.md)
154156
- [`@hideconstructor`](./tags/hideconstructor.md)
155157
- [`@ignore`](./tags/ignore.md)

site/tags/function.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
title: "@function"
3+
---
4+
5+
# @function
6+
7+
**Tag Kind:** [Modifier](../tags.md#modifier-tags)
8+
9+
If a variable declaration is callable and does not have a type declaration,
10+
TypeDoc may convert it as a function. Sometimes, even if a type declaration
11+
is specified, it is desirable to convert a variable as if it was a function.
12+
13+
This tag will cause TypeDoc to convert the specified variable as a function
14+
even if it has a type declaration. TypeDoc will still refuse to convert the
15+
variable as a function if it contains construct signatures or does not contain
16+
any call signatures.
17+
18+
## Example
19+
20+
```ts
21+
export interface MultiCallSignature {
22+
(): string;
23+
(x: string): string;
24+
}
25+
26+
// Documented as if it was a function with two overloads
27+
/** @function */
28+
export const Callable: MultiCallSignature = () => "";
29+
30+
// Documented as Callable2: MultiCallSignature
31+
export const Callable2: MultiCallSignature = () => "";
32+
33+
// Documented as if it was a function
34+
export const Callable3 = () => "";
35+
```
36+
37+
## See Also
38+
39+
- The [`@namespace`](namespace.md) tag
40+
- The [`@interface`](interface.md) tag

src/lib/converter/symbols.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,12 @@ function convertVariable(
993993
type.getCallSignatures().length &&
994994
!type.getConstructSignatures().length
995995
) {
996-
return convertVariableAsFunction(context, symbol, exportSymbol);
996+
if (
997+
comment?.hasModifier("@function") ||
998+
!(declaration && ts.isVariableDeclaration(declaration) && declaration.type)
999+
) {
1000+
return convertVariableAsFunction(context, symbol, exportSymbol);
1001+
}
9971002
}
9981003

9991004
const reflection = context.createDeclarationReflection(
@@ -1149,6 +1154,8 @@ function convertVariableAsFunction(
11491154
);
11501155
}
11511156

1157+
reflection.comment?.removeModifier("@function");
1158+
11521159
// #2824 If there is only one signature, and there isn't a comment
11531160
// on the signature already, treat the comment on the variable
11541161
// as if it belongs to the signature instead.

src/lib/utils/options/tsdoc-defaults.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export const modifierTags = [
8181
"@inline",
8282
"@interface",
8383
"@namespace",
84+
"@function",
8485
"@overload",
8586
"@private",
8687
"@protected",

src/test/converter/function/function.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ export class Predicates {
193193
* Returns true if fn returns true for every item in the iterator
194194
*
195195
* Returns true if the iterator is empty
196+
* @function
196197
*/
197198
export const all: {
198199
<T>(fn: (item: T) => boolean, iterator: Iterable<T>): boolean;

src/test/converter/function/specs.json

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,9 @@
437437
"sources": [
438438
{
439439
"fileName": "function.ts",
440-
"line": 197,
440+
"line": 198,
441441
"character": 13,
442-
"url": "typedoc://function.ts#L197"
442+
"url": "typedoc://function.ts#L198"
443443
}
444444
],
445445
"signatures": [
@@ -452,9 +452,9 @@
452452
"sources": [
453453
{
454454
"fileName": "function.ts",
455-
"line": 198,
455+
"line": 199,
456456
"character": 4,
457-
"url": "typedoc://function.ts#L198"
457+
"url": "typedoc://function.ts#L199"
458458
}
459459
],
460460
"typeParameters": [
@@ -484,9 +484,9 @@
484484
"sources": [
485485
{
486486
"fileName": "function.ts",
487-
"line": 198,
487+
"line": 199,
488488
"character": 12,
489-
"url": "typedoc://function.ts#L198"
489+
"url": "typedoc://function.ts#L199"
490490
}
491491
],
492492
"signatures": [
@@ -499,9 +499,9 @@
499499
"sources": [
500500
{
501501
"fileName": "function.ts",
502-
"line": 198,
502+
"line": 199,
503503
"character": 12,
504-
"url": "typedoc://function.ts#L198"
504+
"url": "typedoc://function.ts#L199"
505505
}
506506
],
507507
"parameters": [
@@ -570,9 +570,9 @@
570570
"sources": [
571571
{
572572
"fileName": "function.ts",
573-
"line": 199,
573+
"line": 200,
574574
"character": 4,
575-
"url": "typedoc://function.ts#L199"
575+
"url": "typedoc://function.ts#L200"
576576
}
577577
],
578578
"typeParameters": [
@@ -602,9 +602,9 @@
602602
"sources": [
603603
{
604604
"fileName": "function.ts",
605-
"line": 199,
605+
"line": 200,
606606
"character": 12,
607-
"url": "typedoc://function.ts#L199"
607+
"url": "typedoc://function.ts#L200"
608608
}
609609
],
610610
"signatures": [
@@ -617,9 +617,9 @@
617617
"sources": [
618618
{
619619
"fileName": "function.ts",
620-
"line": 199,
620+
"line": 200,
621621
"character": 12,
622-
"url": "typedoc://function.ts#L199"
622+
"url": "typedoc://function.ts#L200"
623623
}
624624
],
625625
"parameters": [
@@ -659,9 +659,9 @@
659659
"sources": [
660660
{
661661
"fileName": "function.ts",
662-
"line": 199,
662+
"line": 200,
663663
"character": 35,
664-
"url": "typedoc://function.ts#L199"
664+
"url": "typedoc://function.ts#L200"
665665
}
666666
],
667667
"signatures": [
@@ -674,9 +674,9 @@
674674
"sources": [
675675
{
676676
"fileName": "function.ts",
677-
"line": 199,
677+
"line": 200,
678678
"character": 35,
679-
"url": "typedoc://function.ts#L199"
679+
"url": "typedoc://function.ts#L200"
680680
}
681681
],
682682
"parameters": [
@@ -883,9 +883,9 @@
883883
"sources": [
884884
{
885885
"fileName": "function.ts",
886-
"line": 202,
886+
"line": 203,
887887
"character": 16,
888-
"url": "typedoc://function.ts#L202"
888+
"url": "typedoc://function.ts#L203"
889889
}
890890
],
891891
"signatures": [
@@ -898,9 +898,9 @@
898898
"sources": [
899899
{
900900
"fileName": "function.ts",
901-
"line": 202,
901+
"line": 203,
902902
"character": 16,
903-
"url": "typedoc://function.ts#L202"
903+
"url": "typedoc://function.ts#L203"
904904
}
905905
],
906906
"parameters": [
@@ -1592,9 +1592,9 @@
15921592
"sources": [
15931593
{
15941594
"fileName": "function.ts",
1595-
"line": 209,
1595+
"line": 210,
15961596
"character": 7,
1597-
"url": "typedoc://function.ts#L209"
1597+
"url": "typedoc://function.ts#L210"
15981598
}
15991599
],
16001600
"signatures": [
@@ -1607,9 +1607,9 @@
16071607
"sources": [
16081608
{
16091609
"fileName": "function.ts",
1610-
"line": 209,
1610+
"line": 210,
16111611
"character": 14,
1612-
"url": "typedoc://function.ts#L209"
1612+
"url": "typedoc://function.ts#L210"
16131613
}
16141614
],
16151615
"type": {
@@ -1631,15 +1631,15 @@
16311631
"sources": [
16321632
{
16331633
"fileName": "function.ts",
1634-
"line": 208,
1634+
"line": 209,
16351635
"character": 16,
1636-
"url": "typedoc://function.ts#L208"
1636+
"url": "typedoc://function.ts#L209"
16371637
},
16381638
{
16391639
"fileName": "function.ts",
1640-
"line": 209,
1640+
"line": 210,
16411641
"character": 0,
1642-
"url": "typedoc://function.ts#L209"
1642+
"url": "typedoc://function.ts#L210"
16431643
}
16441644
],
16451645
"signatures": [
@@ -1652,9 +1652,9 @@
16521652
"sources": [
16531653
{
16541654
"fileName": "function.ts",
1655-
"line": 208,
1655+
"line": 209,
16561656
"character": 16,
1657-
"url": "typedoc://function.ts#L208"
1657+
"url": "typedoc://function.ts#L209"
16581658
}
16591659
],
16601660
"type": {

src/test/converter2/issues/gh2307.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const double = times(2);
44

55
export const foo = () => 123;
66

7+
/** @function */
78
export const all: {
89
<T>(fn: (item: T) => boolean, iterator: Iterable<T>): boolean;
910
<T>(fn: (item: T) => boolean): (iterator: Iterable<T>) => boolean;

src/test/converter2/issues/gh2436.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ function bugInner(): { foo: string } {
77
return { foo: "bar" };
88
}
99

10+
/** @function */
1011
export const bug: {
1112
(): { foo: string };
1213
foo: typeof foo;

src/test/converter2/issues/gh2478.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** @function */
12
declare const test: (options?: test.Options) => void;
23

34
declare namespace test {

0 commit comments

Comments
 (0)