Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export the InferOptions and InferArguments type helpers #62

Closed

Conversation

nipunn1313
Copy link

This allows callers to write helper methods that manipulate commands (eg to add options to a preexisting command)

This is technically already possible if you rely on type inference, but I've run into:

error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.

Pull Request

Problem

It is not possible (I believe) to type methods like this

export function addMyCustomOptions<
  Args extends any[],
  Opts extends OptionValues
>(command: Command<Args, Opts>, action: string) {
  return command.option("--custom-thing");
}

If ts can infer the return type, things are fine, but sometimes it gives:
error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.

In this case, I believe we would need InferOptions which is private

Solution

Make InferOptions type exported.

ChangeLog

This allows callers to write helper methods that manipulate commands (eg
to add options to a preexisting command)

This is technically already possible if you rely on type inference, but
I've run into:

error TS7056: The inferred type of this node exceeds the maximum length
the compiler will serialize. An explicit type annotation is needed.
@nipunn1313
Copy link
Author

I am open to other solutions. These exported types would work, but don't seem ideal.

@shadowspawn
Copy link
Contributor

If ts can infer the return type, things are fine, but sometimes it gives:

error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.

Did you see this error on a branch where you had added this to the action handler?

We saw some similar problems in some different approaches to the type inference:

@nipunn1313
Copy link
Author

It wasn't a this it was just a long chain of

export function addMyOptions<...>(command: Command<Args, Opts>) {
  command
    .addOption(new Option())
    .addOption(new Option())
    // .{about 5-7 of these, some including .conflicts()}
}

The output type of that function was not inferable - and tsc gave that error.

I actually found a workaround which was splitting the function into two halves and having all the callsites call both of the methods. The workaround kinda sucks. You can't write a helper to call the two helpers because it overloads tsc in this way.

@shadowspawn
Copy link
Contributor

Somewhat related issue: #32

@nipunn1313
Copy link
Author

yeah - perhaps there's some way to to reduce complexity on typescript via some kind of optimization to mitigate this.

I was running into it with just 5-7 options which feels... too quick.

Seems like typescript has some limit at 50 recursion depth https://github.com/bluepichu/ctf-challenges/blob/d83b02dffe2c7d2404c3fa0c27da886d61ff4c98/plaidctf-2020/thats_a_lot_of_fish/handout/tsc.js.diff

@shadowspawn
Copy link
Contributor

I have not got my head around the issue yet. I found a mention of that error message with a fix from a Typescript guru but not sure if it is relevant. Posting for future reading!

@shadowspawn
Copy link
Contributor

Did you see this error on a branch where you had added this to the action handler?

That was a misguided question sorry. A few PR were opened in short time frame and I assumed they were all related!

@shadowspawn
Copy link
Contributor

Have you got a reproduction? What version of Typescript? I am up to 20 options in a toy program and not had an error yet. I am interested in reproducing, and wondering whether it is a particular method call that is the problem, or basically just lots and lots of type inference.

function addMyOptions<Args extends any[] = [], Opts extends OptionValues = {}>(command: Command<Args, Opts>) {
    return command
        .addOption(new Option('-a, --aaa'))
        ...
        .addOption(new Option('--A <value>').preset('A').default('D'))
        ...
);

const program = new Command()
   .option('--port <number>', 'port number', parseFloat, 80)
   .argument('[rest...]');

const fullProgram = addMyOptions(program);

@nipunn1313
Copy link
Author

I have a non-minimal repro in our codebase. Let me see if I can extract it.

@shadowspawn
Copy link
Contributor

Was addMyOptions being included in a TypeScript definition file? I notice that the error in microsoft/TypeScript#43817 only occurs when generating a definition file.

@shadowspawn
Copy link
Contributor

shadowspawn commented Mar 16, 2024

It is technically easy to export more types, but I don't want to do so without understanding the problem it is solving. I will close this for now, but if you want to keep working on this @nipunn1313 then I can reopen.

Feel free to open a new issue if it comes up again, with new information and renewed interest.

Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants