lukeautry / tsoa

Build OpenAPI-compliant REST APIs using TypeScript and Node
MIT License
3.32k stars 481 forks source link

GenerateMetadataError: Unknown type: IndexedAccessType #1622

Open douglasg14b opened 2 months ago

douglasg14b commented 2 months ago

Sorting

I found several referneced, but they all appeard to be fixed...?

Expected Behavior

When I tun tsoa routes the following controller fails:

export type BaseIVR3Config = {
    walkingSkeletonPath: WalkingSkeletonPath;
    bestMovies: BestMovies;
};

export type BaseIVR3ConfigKey = keyof BaseIVR3Config;
export type BaseIVR3ConfigValue = BaseIVR3Config[BaseIVR3ConfigKey]; // WalkingSkeletonPath | BestMovies

type WalkingSkeletonPath = 'A' | 'B';
type BestMovies = {
    title: string;
    year: number;
}[];

@Route('config2')
export class Config2Controller extends Controller {
    constructor(private useCases: ConfigUseCases) {
        super();
    }

    @Get('{key}')
    async getByKey(@Path() key: BaseIVR3ConfigKey): Promise<BaseIVR3ConfigValue | 'error'> {
        const result = await this.useCases.getByKey(key);

        if (result.ok) {
            return result.value.value;
        }

        return 'error';
    }
}

Current Behavior

This fails with:

Generate routes error. GenerateMetadataError: Unknown type: IndexedAccessType This was caused by 'BaseIVR3Config[BaseIVR3ConfigKey] | 'error''

Possible Solution

Unknown

Steps to Reproduce

Use the above code with tsoa

Context (Environment)

Version of the library: 6.2.1 Version of NodeJS: 18.13.0

Detailed Description

N/A See above

Breaking change?

github-actions[bot] commented 2 months ago

Hello there douglasg14b 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

douglasg14b commented 2 months ago

Oh, found another, is this the same problem? I see other issues like this that appear to be solved 🤔

Indexed types like this make up a majority of any typings we have when it comes to configuration or definitions. It's almost impossible to avoid index types through the entire type tree as they are a fundamental part of most TS usage.

Is there any particular reason that: type Response = WalkingSkeletonPath | BestMovies is fine but type Response = BaseIVR3Config[BaseIVR3ConfigKey] does not even though they are both union types?

https://github.com/lukeautry/tsoa/issues/1375

douglasg14b commented 2 months ago

Hm, this is actually causing a lot of pain at multiple layers, I wonder how to work around it.

github-actions[bot] commented 1 month ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

douglasg14b commented 1 month ago

Bad bot.

How to speedrun fragmented information & hidden problems 101.

WoH commented 1 month ago

Would you like to submit a PR to fix this issue?

douglasg14b commented 2 weeks ago

@WoH I actually went through and tried to understand how this works, and honestly submitting a PR for this is quite the task since I have no context on the codebase, and there isn't much in the way of guidance on the decisions that have been made, or how to navigate them. There's cruft, but not much that explains it, where to look, how things are put together, why various "things" are the way they are, resources...etc

I'm guessing that's a 10-40h task, or even longer. Someone who is already familiar with how TSOA is put together, and has this context may be able to do this in just a few hours.

At the very minimum, someone knowledgeable should provide design guidance, learning resources, and other information to get someone started on this problem.

WoH commented 1 week ago

Sure, I can give you some guidance:

The first step is to debug this construction by both the Parser, as well as the information the type checker provides.

These are the 2 possible sources, TS has some information on both of these here:

https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API

To quickly visualize the AST, this is a great tool:

https://ts-ast-viewer.com/#

IIRC there's a TS discord channel where you can probably also ask for help w/r/t making sense of the Type you want to convert.

Then, tsoa is actually pretty simple, once you understand the idea.

We go though all the class declarations with a Controller Annotation and work through them. Controller -> Method -> Collect inputs, collect outputs. The TypeResolver does TS Type -> generic OpenAPI type (Metadata) From this metadata, we generate

E: In your case, take a look around here: https://github.com/lukeautry/tsoa/blob/master/packages/cli/src/metadataGeneration/typeResolver.ts#L454