typedoc icon indicating copy to clipboard operation
typedoc copied to clipboard

Expand union types

Open FreePhoenix888 opened this issue 1 year ago • 5 comments

Search Terms

expand, imported, types

Problem

Code: https://github.com/deep-foundation/capacitor-device/blob/6d6eae584c3567c5e381fc8a68f733e157d1ab85/src/device-info.ts#L1

import { BatteryInfo, GetLanguageCodeResult, LanguageTag, DeviceInfo as DeviceGeneralInfo } from "@capacitor/device";
export type DeviceInfo =
  | DeviceGeneralInfo
  | BatteryInfo
  | { languageCode: GetLanguageCodeResult['value'] }
  | { languageTag: LanguageTag['value'] };

I get such documentation:

DeviceInfo: DeviceGeneralInfo | BatteryInfo | {
    languageCode: GetLanguageCodeResult["value"];
} | {
    languageTag: LanguageTag["value"];
}

I would like typedoc to expand those types. Example:

DeviceInfo: {
  model: string;
  isCharging: boolean;
  ...
}

Suggested Solution

typescript-json-schema is able to find all the actual properties of DeviceInfo and their descriptions

freephoenix888@freephoenix888:~/Programming/deep/capacitor-device$ typescript-json-schema ./src/device-info.ts DeviceInfo
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "anyOf": [
        {
            "$ref": "#/definitions/DeviceInfo_1"
        },
        {
            "$ref": "#/definitions/BatteryInfo"
        },
        {
            "properties": {
                "languageCode": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        {
            "properties": {
                "languageTag": {
                    "type": "string"
                }
            },
            "type": "object"
        }
    ],
    "definitions": {
        "BatteryInfo": {
            "properties": {
                "batteryLevel": {
                    "description": "A percentage (0 to 1) indicating how much the battery is charged.",
                    "type": "number"
                },
                "isCharging": {
                    "description": "Whether the device is charging.",
                    "type": "boolean"
                }
            },
            "type": "object"
        },
        "DeviceInfo_1": {
            "properties": {
                "diskFree": {
                    "description": "How much free disk space is available on the normal data storage\npath for the os, in bytes.\n\nOn Android it returns the free disk space on the \"system\"\npartition holding the core Android OS.\nOn iOS this value is not accurate.",
                    "type": "number"
                },
                "diskTotal": {
                    "description": "The total size of the normal data storage path for the OS, in bytes.\n\nOn Android it returns the disk space on the \"system\"\npartition holding the core Android OS.",
                    "type": "number"
                },
                "isVirtual": {
                    "description": "Whether the app is running in a simulator/emulator.",
                    "type": "boolean"
                },
                "manufacturer": {
                    "description": "The manufacturer of the device.",
                    "type": "string"
                },
                "memUsed": {
                    "description": "Approximate memory used by the current app, in bytes. Divide by\n1048576 to get the number of MBs used.",
                    "type": "number"
                },
                "model": {
                    "description": "The device model. For example, \"iPhone13,4\".",
                    "type": "string"
                },
                "name": {
                    "description": "The name of the device. For example, \"John's iPhone\".\n\nThis is only supported on iOS and Android 7.1 or above.",
                    "type": "string"
                },
                "operatingSystem": {
                    "$ref": "#/definitions/OperatingSystem",
                    "description": "The operating system of the device."
                },
                "osVersion": {
                    "description": "The version of the device OS.",
                    "type": "string"
                },
                "platform": {
                    "description": "The device platform (lowercase).",
                    "enum": [
                        "android",
                        "ios",
                        "web"
                    ],
                    "type": "string"
                },
                "realDiskFree": {
                    "description": "How much free disk space is available on the normal data storage, in bytes.",
                    "type": "number"
                },
                "realDiskTotal": {
                    "description": "The total size of the normal data storage path, in bytes.",
                    "type": "number"
                },
                "webViewVersion": {
                    "description": "The web view browser version",
                    "type": "string"
                }
            },
            "type": "object"
        },
        "OperatingSystem": {
            "enum": [
                "android",
                "ios",
                "mac",
                "unknown",
                "windows"
            ],
            "type": "string"
        }
    }
}
We can see how they implement that feature and do the same for this library :)

FreePhoenix888 avatar Jun 05 '23 12:06 FreePhoenix888

That's a union type..

I have been considering a @inline tag which would control this behavior, not much time to work on typedoc recently though.

Gerrit0 avatar Jun 11 '23 19:06 Gerrit0

a @inline tag which would control this behavior

It would be excellent! I often come out to the situation where I want to @link field from the type but that type is a union type :(

FreePhoenix888 avatar Jun 12 '23 14:06 FreePhoenix888

@Gerrit0 You'll have to make sure such a tag can force rendering behavior in both the "expand" and "link" directions - the are situations where you want both, and it depends on code semantics that TypeDoc can't possibly know about. Also note that the present behavior does not necessarily always link or always expand - it differs depending on which part of the generated documentation you're in. Lower bounds on generic type parameters are always expanded in full, for example, while type declarations only expand if the component type is not present in the generated documentation.

I also think @inline is a bit ambiguous as a name, since both expansion and linking to component types are done inline in the visible TS declaration. Consider @expand or @noexpand instead, maybe?

I'm trying to convince my workplace to give me some time to spend on a plugin that does this, because we desperately need it.

Oblarg avatar Jun 12 '23 15:06 Oblarg

It would be nice if @expand tag could also process/expand nested generics like

type CompicatedGeneric<X, Y, Z> = Awaited<X> & ReturnType<Y> | Required<Parameters<Z>>

/**
  @expand
**/
type GenericInstance = CompicatedGeneric<typeof somePromise, typeof someFn, SomeClass['method']>

->

GenericInstance = {
  a: string;
  b: Uint8Array;
  c: bigint;
}

Looks like related issue

devDesu avatar Jun 13 '23 11:06 devDesu

I'm in favor of the @expand / @noexpand tag or a global configuration to specify the maximum number of characters for deciding not to expand. In my case, the presence of excessively long types makes the page difficult to understand. Here is the link.

Songkeys avatar Aug 31 '23 04:08 Songkeys