If --useTsLinkResolution is turned on (the default) this page may not apply for your links within comments as TypeDoc will use TypeScript's resolution if TypeScript resolved the link. This resolution strategy will only be used if TypeScript fails to parse the link or does not parse the source document (e.g. for external documents and for the readme file).
Some tags like {@link} and {@inheritDoc} can refer to other
members of the documentation. These tags use declaration references to name another declaration.
TypeDoc's declaration references are slightly different than JSDoc's namepaths. They are based off of the "new" TSDoc declaration references with slight modifications to make their resolution behavior more closely match the TypeScript language service (e.g. what VSCode does).
Declaration references are comprised of an optional module source, a component path, and an optional meaning. Once parsed, they are resolved according to the resolution strategy described below.
The first part of a declaration, up to a ! is parsed as the module source. This will be taken
literally and used to refer to the module name in a multiple entry point documentation site.
It should not include the path to the module file.
If a declaration reference does not contain a !, then it does not contain a module source, and the
first part of the declaration reference is the component path.
/**
* {@link moduleA!}
* {@link "with!bang and \"quoted path\""!}
*/
After the module source, declaration references contain a component path, which is made up of one
or more component names delimitated by a ., #, or ~.
The deliminator is used to determine how to navigate the project tree.
| Deliminator | Behavior |
|---|---|
. |
The most general purpose deliminator. It will first try to resolve exports and static class properties, but will also resolve members if no export is found for improved compatibility with TypeScript's resolution. |
# |
Indicates that the next component is a "member", including class instance properties, interface members, and enum members. |
~ |
Indicates that the next component is an export of a namespace/module. |
The TSDoc specification says that ~ traverses via locals. This is
different than TypeDoc's behavior. TypeDoc will treat ~ as a stricter .
which only supports navigating to a namespace/module export. It should
generally be avoided in favor of . for improved compatibility with VSCode.
// module.ts
/**
* {@link module!Foo}
* {@link Foo}
*/
export namespace Foo {
/**
* {@link module!Foo.Bar}
* {@link module!Foo~Bar}
* {@link Foo~Bar}
*/
export namespace Bar {
/**
* {@link module!Foo.Bar.Baz}
* {@link module!Foo~Bar~Baz}
* {@link Bar~Baz}
* {@link Baz}
*/
export class Baz {
/**
* {@link Baz#prop}
*/
prop = 123;
/**
* {@link Baz.prop}
*/
static prop = 456;
/**
* {@link Baz#instanceOnly}
* {@link Baz.instanceOnly} also works as there is no conflicting static
*/
instanceOnly = 789;
}
}
}
If no module source is specified, by default component paths are resolved relative to the scope where
they are declared (note: Modules and namespaces create a new scope. Classes, interfaces, and object types
do not). This is sometimes inconvenient if a name is shadowed. To refer to a name with resolution starting
in the the root scope, an empty module source can be specified with !.
export const Target = 1;
export namespace Foo {
export const Target = 2;
/**
* {@link Target} links to 2
* {@link !Target} links to 1
*/
export const Source = 3;
}
While classes and interfaces do not normally create a new scope, the TypeScript language service will check their members for link targets when resolving links starting at the class/interface declaration. TypeDoc mimics this behavior, but be aware that links that do not contain the class/interface name will prefer targets in their normal scope.
export const dup = 1;
/**
* {@link dup} links to 1
* {@link target} links to 2
* {@link Foo.dup} links to 3
*/
export class Foo {
target = 2;
dup = 3;
}
The final part of a declaration reference is an optional meaning which can be used to disambiguate references which could otherwise refer to multiple documentation items. The meaning can also be used to refer to a specific overload or type of declaration.
The meaning takes one of the following forms:
:keyword where keyword is described by the list below.:keyword(decimal digits) where decimal digits indicates the index of an overloaded meaning:(decimal digits) shorthand for an overloaded meaning:decimal digits shorthand for an overloaded meaning:label where label refers to a declaration by its
{@label} tag. label may contain A-Z, 0-9, and _
and may not start with a number. Note: This meaning parse is specific to
TypeDoc, and is not currently specified by the TSDoc standard.The keywords recognized by TypeDoc are:
class - Refers to reflections which represent a class.interface - Refers to reflections which represent an interface.type - Refers to reflections which represent some type.enum - Refers to reflections which represent an enum.namespace - Refers to reflections which represent a namespace.function - Refers to reflections which represent a function's or method's signatures.var - Refers to reflections which represent a variable.constructor - Refers to the constructor of a class or type.member - Refers to reflections which represent an enum member, property, method, or accessor.event - Permitted to conform with the TSDoc spec, but will result in a broken reference.call - Refers to reflections which represent a function's or method's signatures.new - Refers to the constructor of a class or type.index - Refers to a reflection's index signatures.complex - Refers to reflections which represent some type.getter - (TypeDoc specific, 0.23.3+) Refers to the get signature of an accessor.setter - (TypeDoc specific, 0.23.3+) Refers to the set signature of an accessor./**
* {@link foo:0}
* {@link foo:function}
* {@link foo:(0)}
* {@link foo:function(0)}
* {@link foo:NO_ARGS}
* {@label NO_ARGS}
*/
function foo(): void;
/**
* {@link foo:1}
* {@link foo:function(1)}
* {@link foo:(1)}
* {@link foo:NUM_ARG}
* {@label NUM_ARG}
*/
function foo(n: number): number;
/**
* {@link foo:2}
* {@link foo:function(2)}
* {@link foo:(2)}
* {@link foo:STR_ARG}
* {@label STR_ARG}
*/
function foo(s: string): string;
When resolving links TypeDoc resolves the module source, then the component path, and finally the meaning.
Link resolution is most easily understood with an example, the following project structure will be used in examples below:
project "My lib docs"
module "@me/lib"
class "Foo"
static property "bar"
property "bar"
method "baz"
signature 0 () => string
signature 1 (x: number) => number
type alias "Bam"
function "Bam"
signature 0 () => string
signature 1 (x: number) => number
namespace "Nested"
variable "Bam"
module "@me/lib2"
function "Bop"
Resolve the Module Source:
TypeDoc first checks if a module is specified before !. If a module source is specified, then TypeDoc
will get the root level reflection with the same name as the module. In the example above, @me/lib!
and @me/lib2! will be resolved to the expected module, but @me/fake! will fail to resolve.
If the declaration reference does not specify a module source but starts with ! then the link is treated
as a globally specified link whose resolution starts at the project level. !"@me/lib" will also resolve
to that module.
Otherwise, the link is treated as a local link which should start resolution at the comment location.
TypeDoc will prioritize link resolution with fewer scope steps to the target, but will also check parents
of a reflection for the link target. That is, {@link Bam} within the Nested namespace will resolve
to @me/lib.Nested.Bam, but {@link Bam} in the Foo class's comment (or the property/method) will
resolve to @me/lib.Bam.
Resolve the Component Path:
Component paths are resolved according to their delimiter. The first section of a component path
is resolved as if the delimiter is ..
If the delimiter is ., TypeDoc will look for children of the current reflection, prioritizing
exports and static attributes over member attributes. The link {@link @my/lib!Foo.bar} will link
to the static property rather than the instance property, but {@link my/lib!Foo.baz} will successfully
link to the method even though it isn't static.
If the delimiter is #, TypeDoc will look for class/interface instance members. The link
{@link @my/lib!Foo.bar} will link to the instance property.
If the delimiter is ~, TypeDoc will only look for children of the current reflection if the
current reflection is a module. This delimiter isn't generally useful.
Resolve the Meaning:
Meanings are used to disambiguate links which could be intended to go to multiple locations.
The keyword portion of the meaning is resolved first. {@link @my/lib!Bam:type} will link
to the type alias, while {@link @my/lib!Bam:function} will link to the function.
Meanings may also include an index which further disambiguates the link. If you wanted to link
to the second signature of the Bam function, {@link @my/lib!Bam:function} is insufficient
and {@link @my/lib!Bam:function(1)} must be used instead.
An index may be included in a meaning without the keyword. This would be sufficient for linking
to the first signature of the baz method: {@link @my/lib!Foo.baz:0}, but the Bam function
is also merged with a type alias, so {@link @my/lib!Bam:0} could link to either the type alias
or the first signature of the function.
When TypeDoc fails to resolve a link (and the validation.invalidLink option is set), TypeDoc will print a warning like the following:
[warning] Failed to resolve link to "Foo" in comment for @me/lib2.Bop
With the resolution strategy in mind, we can now manually apply TypeDoc's link resolution algorithm to determine where the resolution went wrong.
!, so it will be resolved as a local link, starting from the function @me/lib2.Bop@my/lib2.Bop doesn't have any children named Foo@my/lib2 doesn't have any children named FooFooGiven that we wanted to link to the Foo class in @my/lib, we have a couple options:
Change the link to {@link @my/lib!Foo}
This is the recommended change as it means TypeDoc doesn't need to walk up multiple scopes to find the link, it can start at the project root, then go directly to the module and then the class.
Change the link to {@link "@my/lib".Foo}
With this change, TypeDoc would resolve the link, but still has to check @my/lib2.Bop and @my/lib2
for a child named @my/lib before reaching the root project.