typedoc
typedoc copied to clipboard
Utility functions are included in output, instead of their resolved final types
Search terms
Maybe this is intended (or isn't implemented yet), but Utility type exports aren't being expanded in the output and instead show "Omit<>"...
export interface TSmarterLabelOptions {
color: string;
text: string;
};
export type TOptions = Omit<TGlobalOptions, 'text'>;
Expected Behavior
I expect our clients to see the final result of the types involved in Utility functions:
Actual Behavior
This is especially problematic when re-exporting a type from another project and omitting a value (where we don't want them to know anything about the other project) and the end-users don't know what we're omitting from. This is actually how we use it:
import type { TGlobalOptions } from '../../another_project_by_tsconfig_reference';
export type TOptions = Omit<TGlobalOptions, 'text'>;
Environment
- Typedoc version: 0.20.28
- TypeScript version: 4.1.5
- Node.js version: 12.18.4
- OS: 10.15.7
Some utility types are really complex. I kind of hope my utility type won't get expanded in the docs 😉
type ExtractTypeFromSelectArg<
DB,
TB extends keyof DB,
S,
A extends keyof any,
R = RowType<DB, TB>
> = S extends `${infer SC}.${infer T}.${infer C} as ${infer RA}`
? RA extends A
? `${SC}.${T}` extends TB
? C extends keyof DB[`${SC}.${T}`]
? DB[`${SC}.${T}`][C]
: never
: never
: never
: S extends `${infer SC}.${infer T}.${infer C}`
? C extends A
? `${SC}.${T}` extends TB
? C extends keyof DB[`${SC}.${T}`]
? DB[`${SC}.${T}`][C]
: never
: never
: never
: S extends `${infer T}.${infer C} as ${infer RA}`
? RA extends A
? T extends TB
? C extends keyof DB[T]
? DB[T][C]
: never
: never
: never
: S extends `${infer T}.${infer C}`
? C extends A
? T extends TB
? C extends keyof DB[T]
? DB[T][C]
: never
: never
: never
: S extends A
? S extends keyof R
? R[S]
: never
: S extends AliasedRawBuilder<infer O, infer RA>
? RA extends A
? O
: never
: S extends (qb: any) => AliasedRawBuilder<infer O, infer RA>
? RA extends A
? O
: never
: S extends AliasedQueryBuilder<any, any, infer O, infer QA>
? QA extends A
? ValueType<O>
: never
: S extends (qb: any) => AliasedQueryBuilder<any, any, infer O, infer QA>
? QA extends A
? ValueType<O>
: never
: never
I feel like the purpose of documentation isn't to show the inner workings, but to show how one would use a library/api, etc. Is this not the purpose of this project? Can this be opt in?
This is a similar request to #1513.
I think this might make sense to do - with some limitations.
- This should only happen if the type alias has no type parameters. This looks like an interface
This does not:type Foo = Record<"a" | "b", string>type Bar<T> = T extends string ? T : never - This should only happen if the type is an object type.
type Yes = { a: string } type No = { a: string } | { b: number } - This should still happen if the type is an intersection type
type Yes = { a: string } & { b: number } - This should not happen for tuple types
type No = [a: string, b: number]
Am I missing anything here? This won't catch the following, which it might be argued should be caught....
type Missed<T> = Record<"a" | "b", T>
cc: @thebestnom
I'm not sure this is something that I necessarily want to put in the core library - but https://github.com/mxsdev/ts-expand-type exists now, the code in which should be usable to create a plugin... putting this here so I remember the next time I look at this with an eye to implementing.
@Gerrit0 What are your thoughts on having the outputted types match those shown by the language service (in tooltips and such)?
It feels like that would make for a nice overall user experience, since users would know exactly what the doc typings would be just by looking at the tooltips in their IDE. Ideally the implementation could even leverage some compiler/language service APIs to do the type resolution, although I'm not sure if such APIs exist.
The language service is unfortunately terrible (at least last I looked at it... been a couple years) in terms of providing an API that can be used to correctly associate a displayed type name with the type that it actually represents. Because it just displays types to the user without go to definition, it will just stringify a type and then pass it through syntax highlighting... If that weren't the case, I think it'd be the way to go.
(Maybe this has improved now that semantic highlighting is a thing? Open to a PR resulting from an investigation!)
Are there any good solutions now? I see that vscode and idea floating window prompt both support this, can you refer to the logic of this section?like this:

Someone gave an answer to this issue: https://github.com/TypeStrong/typedoc/issues/2032. I have tested it and it can be used normally
0.24.0-beta.6 includes support for this, with a slight design change. I realized that it doesn't necessarily always make sense to treat a type alias as an interface with eagerly resolved properties, and some people may prefer keeping the constructing type, (Record<keyof Foo, string> might be better for docs if Foo has a ton of properties)
Thus, resolving the type is now opt-in with the @interface tag. For convenience, @prop and @property are supported for specifying comments on the properties of the resulting type.
An example:
/**
* Foo docs
*/
export type Foo = {
/**
* Foo.a docs
*/
a: 123;
/**
* Foo.b docs
*/
b: 456;
};
/**
* Bar docs
* @property a Bar.a docs
* @interface
*/
export type Bar = {
[K in keyof Foo]: string;
};
With this setup, Bar could be equivalently defined as:
/** Bar docs */
export interface Bar {
/** Bar.a docs */
a: 123,
/** Foo.b docs
b: 456,
}
Notice that a's comment is overridden, but bs comment is still the one declared on the source type.