Skip to content

Deducing return types from boolean arguments does not work with JSDoc and default argument values #59214

Closed as not planned
@Darker

Description

@Darker

🔎 Search Terms

🕗 Version & Regression Information

I don't know how to determine the exact version VSCode is using, but I just updated it...

⏯ Playground Link

https://www.typescriptlang.org/play/?jsx=0&filetype=js#code/C4TwDgpgBAKuEGEAWB7AlgYwgHhlCAHsBAHYAmAzlAEYooA2EAhiQDSwBiaAThcOzADKEDCnIA+KAF5Y+IqUpRg3AK7QA-Jx58oALljDR5ANwAoU6EhQAIiKYgAovPIVc7ABpziL2JJkwzUwB6ACoQ0ygQqAABYgBbMHomYigAb1oGZhIAXygANQAlCGAVbhIKADkVOOoIbgio6LAmbiY4tNsMeydvSmwMxhZ2QuLS8qqauvFc7lGyyura7igGmNmS+bS4SGR0LGwRjfHFuvYSE+52Pm40EgBzaYag0wAzFRIMYDQxKHWxgCEQLtMBAABR-eYTJbSJSqCAASjSESgKORKKCQRiwAoAFo0HcSChZmjfnMSFBzvR6GZsuYjDoKKgVPQyP8IFC6jCISRAcCsKDlGp4WZ6cAoIyUMzWRBBMpbncuWTeagQaCXkx6BQEWYMVAAIKfFQaqBIW7AfSi8VMll6zUoNkc7j6a7yqAAHwpF1MlolUttFHt7IuiqOyr2YOF5iAA

💻 Code

This problem occurs when trying to use JSDoc with TypeScript conditional types. The conditional type I created is the following:

type TypeChoice<T extends boolean, TFirst, TSecond> = T extends true ? TFirst : TSecond;

Application in plain javascript:

/**
 * @template {boolean} VReturnsNumber
 * @param {VReturnsNumber} returnsNumber 
 * @returns {TypeChoice<VReturnsNumber, number, string>}
 */
// Error in the argument: 
// Type 'boolean' is not assignable to type 'VReturnsNumber'.
//   'boolean' is assignable to the constraint of type 'VReturnsNumber',
//   but 'VReturnsNumber' could be instantiated with a different subtype of constraint 'boolean'.ts(2322)
function returnByChoice(returnsNumber = true) {
    
    // @ts-ignore
    return null;
}

// These two work fine and show the desired type
const shouldBeNumber = returnByChoice(true);
const shouldBeString = returnByChoice(false);
// Actual hint: const shouldAlsoBeNumber: string | number
// default argument is not applied
const shouldAlsoBeNumber = returnByChoice();

🙁 Actual behavior

Error on the default argument:

Error in the argument: 
Type 'boolean' is not assignable to type 'VReturnsNumber'.
  'boolean' is assignable to the constraint of type 'VReturnsNumber',
  but 'VReturnsNumber' could be instantiated with a different subtype of constraint 'boolean'.ts(2322)

Additionally, the type is unknown if no argument is provided.

🙂 Expected behavior

  • The default argument should not cause an error. At the very least, it should not cause an error when the base type for the template is a primitive type
  • The default arguments should be used to infer the template if possible

Additional information about the issue

I also tried to use this to suppress the error, but it kills the type inference in the process (the result type is always number | string):

type DecayExtends<T, X extends T> = T;
/**
 * @template {boolean} VReturnsNumber
 * @param {DecayExtends<boolean, VReturnsNumber>} returnsNumber 
 * @returns {TypeChoice<VReturnsNumber, number, string>}
 */
function returnByChoice(returnsNumber = true) {
    
    // @ts-ignore
    return null;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions