Closed as not planned
Closed as not planned
Description
🔎 Search Terms
- typescript template default argument
- jsdoc infer template from default argument
- I found this but it is closed so probably not the same issue: default types for @template generics in JSDoc #29401
🕗 Version & Regression Information
I don't know how to determine the exact version VSCode is using, but I just updated it...
⏯ Playground Link
💻 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;
}