Skip to content

Wrong inference for defaulted generic in nested callΒ #63380

@TurtIeSocks

Description

@TurtIeSocks

πŸ”Ž Search Terms

nested generic call inline inference contextual typing function calls default type parameter

πŸ•— Version & Regression Information

  • I see the same issue from version 4.1.5 to nightly in TypeScript Playground

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=6.0.0-dev.20260401#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwCsctUAeAFXhAA8MRVgBneRjGEgcwBp4BVK2vSYs2nHgDUBdBs1btUHeAF54AclUA+ABStYGAFzxyPIYd49GIAA4B+Q+ICUhgAYASAN7kAvh-E-3vF7OAFCgkLAIKOjYeAJW4BgU2gBuUBDIIIbkTvDu8Bg4AEIgWjTxmCDAWTnJxMDwXsHBZQlaRCRaqgASIBAQOKo8qgDqODAQwKoODgB0BcWdPX04o+OTDvAA9JvwAEZQwE1geKzwAO5YGAAWOMgYAMrWsFAFMMqExKiLvf2DaqsTKbBbbwUHwAB6Nma1HKGC0F2utweTxgLzGs3mJQAREt+gDgFiNiCODgcIdobC2p9vss-iMxoChmppnMiiVuj8cPB8VMtjsSWTgkA

πŸ’» Code

declare function join<T extends string, U extends string, V extends string = ''>(start: T, end: U, sep?: V): `${T}${V}${U}`
declare function expect<T>(value: T): { toBe(expected: T): void }

expect(join('Hello', 'World')).toBe('HelloWorld') // bad

const withoutSeparator = join('Hello', 'World')
//    ^? const withoutSeparator: "HelloWorld"
expect(withoutSeparator).toBe("HelloWorld") // good

expect(join('Hello', 'World', ' ')).toBe('Hello World') // good

πŸ™ Actual behavior

TypeScript does not infer the return types correctly of a nested function call when an optional generic param is omitted, even if a default is provided. When the function call is not nested, it is inferred correctly. It is also inferred correctly when all params are provided.

πŸ™‚ Expected behavior

I would expect that both of these approaches would compile:

expect(join('Hello', 'World')).toBe('HelloWorld') // bad

const withoutSeparator = join('Hello', 'World')
expect(withoutSeparator).toBe("HelloWorld") // good

Additional information about the issue

There are very similar issues, such as #54184, #56714, and #62680 but they didn't quite match up to what I'm seeing here, particularly since the reproductions are quite a bit more complex.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions