Skip to content

Incorrect any displayed in type with noErrorTruncation: trueΒ #62032

Closed

Description

@typeholes

πŸ”Ž Search Terms

noErrorTruncation

πŸ•— Version & Regression Information

  • This changed between versions 5.8.3 and 5.9 beta

⏯ Playground Link

https://www.typescriptlang.org/play/?noErrorTruncation=true&ts=5.9.0-dev.20250709#code/C4TwDgpgBAKlC8UDaAoKUCMAaATFgzFgCxYCsWAbFgOxYAcWAnFgAxZqa4HFmU31NW7dNjyES5KrQbM2HUdwl9pguSK7jeUgbOGcxPSfxlD5Gw8p2n1BpdpNr9ircdV6Fmoyt1nbL79ZOnpYO7uZ2rj42zl5Wjh4W9m6+MSHJ0cFJUVAA5ADOwACWADbFUADmAPaVACY5WLkAdpUA7lDAAE4Aro0AxgCGRY3lOSgAuihAA

πŸ’» Code

type T = [
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  1,2,3,4,5,6,7,8,9,0,
  'still good', 'now truncating'
]
// type shows any in hover in place of 'still good'  this is where the elision would be without noErrorTruncation

πŸ™ Actual behavior

type shows any where the elision would have been without noErrorTruncation.

πŸ™‚ Expected behavior

full type is shown.

Additional information about the issue

This is only in the display. type checking behaves correctly and indexing to that position shows the correct type.

Activity

  1. Andarist commented on Jul 10, 2025

    @Andarist
    Contributor

    This would likely address this "regression":

    diff --git a/src/services/services.ts b/src/services/services.ts
    index 2df3b75ae6..e621a15064 100644
    --- a/src/services/services.ts
    +++ b/src/services/services.ts
    @@ -237,6 +237,7 @@ import {
         noop,
         normalizePath,
         normalizeSpans,
    +    noTruncationMaximumTruncationLength,
         NumberLiteralType,
         NumericLiteral,
         ObjectAllocator,
    @@ -2313,7 +2314,7 @@ export function createLanguageService(
                         nodeForQuickInfo,
                         /*semanticMeaning*/ undefined,
                         /*alias*/ undefined,
    -                    maximumLength ?? defaultHoverMaximumTruncationLength,
    +                    maximumLength ?? (program.getCompilerOptions().noErrorTruncation ? noTruncationMaximumTruncationLength : defaultHoverMaximumTruncationLength),
                         verbosityLevel,
                     ),
             );

    But, truth to be told, noErrorTruncation is only documented to be, well, about error truncation - not about general type display in all sort of places (but I know it has, historically, been used by those too). The potential problem here is that this is somewhat at odds with the new expandable hovers (cc Gabriela Araujo Britto (@gabritto)) and I'd say it probably no longer should impact quick info (as it doesn't now).

    The extra problem is this weird any that gets displayed here. That's a product of those lines of code:
    https://github.com/microsoft/TypeScript/blob/9e20e032effad965567d4a1e1c30d5433b0a3332/src/compiler/checker.ts#L7833-L7839

    This any gets a ... 4 more elided ... comment but that doesn't end up being printed and perhaps it should. That said, any being displayed in those truncating scenarios has always been slightly weird - and actually, IIRC, it can accidentally get leaked into generated .d.ts without producing any errors about the inferred cyclic type not being fully serializable

  2. typeholes commented on Jul 10, 2025

    @typeholes
    Author

    Yes, the problem really is with the any. It is very confusing without the comment.

    Agreed that noErrorTruncation having side effects outside of errors is weird and should be changed. That said, those side effects are often the difference between seeing what I need and having to create some indexed type just to figure out what is going on. From a user perspective it would be ideal if the expandable hovers could expand the elision. That seems like a fairly heavy lift on the implementation side.

  3. gabritto commented on Jul 10, 2025

    @gabritto
    Member

    Basically what Mateusz BurzyΕ„ski (@Andarist) said above, but to reiterate, what I remember happening was that noErrorTruncation affecting hovers was a bit confusing for users and probably not intended. To add to that confusion, a long time ago I think we didn't truncate anything at all, and then we added truncation, and added noErrorTruncation, which was supposed to disable truncation in errors, but because the type printing code is shared, it ended up also disabling truncation in hovers (see #26238).
    Now we have a setting specifically for truncation in hovers: #61662.

    The elision comment on any shouldn't be missing, I agree that's a bug.

  4. typeholes commented on Jul 11, 2025

    @typeholes
    Author

    Do we know what the motivation for creating an any keyword node when noTruncation is true was? I'm waiting on the tests to finish after changing it always create the type reference node, hopefully that will provide more context

  5. gabritto commented on Jul 11, 2025

    @gabritto
    Member

    I took a closer look now, and I think producing the any is intentional.
    The reason why the code exists as it does today is that, if we are printing a type for e.g. a codefix, we don't want to truncate the type, so in that context, we set the NodeBuilder.NoTruncation flag when printing a type. And if even with NodeBuilder.NoTruncation the type printer still hits its hard limit (of 100k characters I think), we don't want to produce the type node reference with an elision name (i.e. factory.createTypeReferenceNode(... ${types.length - i} more ..., /*typeArguments*/ undefined)), because then the code produced by the codefix will have a parsing error. So we instead produce an any with a comment, because that is a valid type.

    Perhaps the root of the problem is that when a config has noErrorTruncation: true, we also set NodeBuilder.NoTruncation in typeToString, even if we're calling typeToString for hover or diagnostics, and in those cases we don't really need to produce an any because the type we print doesn't have to be valid. But then again, if we're printing a type for .d.ts emit, we do want to produce a valid type. So it's tricky.

  6. johtso commented on Jul 19, 2025

    @johtso

    This issue had me chasing my tail for a few hours today thinking that I had a problem with my types.. #62090

  7. locked as resolved and limited conversation to collaborators on Jan 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions