diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 592a759756e17..97a0e99357567 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16372,11 +16372,7 @@ namespace ts { } } } - // We skip inference of the possible `infer` types unles the `extendsType` _is_ an infer type - // if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to - // "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint - // so in those cases we refain from performing inference and retain the uninfered type parameter - if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) { + if (!checkTypeInstantiable) { // We don't want inferences from constraints as they may cause us to eagerly resolve the // conditional type instead of deferring resolution. Also, we always want strict function // types rules (i.e. proper contravariance) for inferences. diff --git a/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.js b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.js new file mode 100644 index 0000000000000..a0231c139f032 --- /dev/null +++ b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.js @@ -0,0 +1,33 @@ +//// [recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts] +export {} +export interface Option { + zip1>>(...others: O): Option<[T, ...UnzipOptionArray1]>; + + zip2>>(...others: O): Option<[T, ...UnzipOptionArray2]>; + + zip3>>(...others: O): Option<[T, ...UnzipOptionArray3]>; +} + +type UnzipOption = T extends Option ? V : never; + +/// This doesn't work +type UnzipOptionArray1 = { [k in keyof T]: T[k] extends Option ? UnzipOption : never }; + +/// But these work +type UnzipOptionArray2 = { [k in keyof T]: UnzipOption }; +type UnzipOptionArray3 = { [k in keyof T]: T[k] extends Option ? V : never }; + +declare const opt1: Option; +declare const opt2: Option; +declare const opt3: Option; + +const zipped1 = opt1.zip1(opt2, opt3); +const zipped2 = opt1.zip2(opt2, opt3); +const zipped3 = opt1.zip3(opt2, opt3); + +//// [recursiveTypeAliasWithSpreadConditionalReturnNotCircular.js] +"use strict"; +exports.__esModule = true; +var zipped1 = opt1.zip1(opt2, opt3); +var zipped2 = opt1.zip2(opt2, opt3); +var zipped3 = opt1.zip3(opt2, opt3); diff --git a/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.symbols b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.symbols new file mode 100644 index 0000000000000..7ecc4ef73390b --- /dev/null +++ b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.symbols @@ -0,0 +1,121 @@ +=== tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts === +export {} +export interface Option { +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 24)) + + zip1>>(...others: O): Option<[T, ...UnzipOptionArray1]>; +>zip1 : Symbol(Option.zip1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 28)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 6)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>others : Symbol(others, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 36)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 6)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 24)) +>UnzipOptionArray1 : Symbol(UnzipOptionArray1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 60)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 6)) + + zip2>>(...others: O): Option<[T, ...UnzipOptionArray2]>; +>zip2 : Symbol(Option.zip2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 88)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 6)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>others : Symbol(others, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 36)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 6)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 24)) +>UnzipOptionArray2 : Symbol(UnzipOptionArray2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 101)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 6)) + + zip3>>(...others: O): Option<[T, ...UnzipOptionArray3]>; +>zip3 : Symbol(Option.zip3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 88)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 6, 6)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>others : Symbol(others, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 6, 36)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 6, 6)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 24)) +>UnzipOptionArray3 : Symbol(UnzipOptionArray3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 66)) +>O : Symbol(O, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 6, 6)) +} + +type UnzipOption = T extends Option ? V : never; +>UnzipOption : Symbol(UnzipOption, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 7, 1)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 17)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 17)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>V : Symbol(V, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 44)) +>V : Symbol(V, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 44)) + +/// This doesn't work +type UnzipOptionArray1 = { [k in keyof T]: T[k] extends Option ? UnzipOption : never }; +>UnzipOptionArray1 : Symbol(UnzipOptionArray1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 9, 60)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 31)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 23)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 31)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>UnzipOption : Symbol(UnzipOption, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 7, 1)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 31)) + +/// But these work +type UnzipOptionArray2 = { [k in keyof T]: UnzipOption }; +>UnzipOptionArray2 : Symbol(UnzipOptionArray2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 12, 101)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 31)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 23)) +>UnzipOption : Symbol(UnzipOption, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 7, 1)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 31)) + +type UnzipOptionArray3 = { [k in keyof T]: T[k] extends Option ? V : never }; +>UnzipOptionArray3 : Symbol(UnzipOptionArray3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 15, 66)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 31)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 23)) +>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 23)) +>k : Symbol(k, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 31)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) +>V : Symbol(V, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 71)) +>V : Symbol(V, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 16, 71)) + +declare const opt1: Option; +>opt1 : Symbol(opt1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 18, 13)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) + +declare const opt2: Option; +>opt2 : Symbol(opt2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 19, 13)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) + +declare const opt3: Option; +>opt3 : Symbol(opt3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 20, 13)) +>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9)) + +const zipped1 = opt1.zip1(opt2, opt3); +>zipped1 : Symbol(zipped1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 22, 5)) +>opt1.zip1 : Symbol(Option.zip1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 28)) +>opt1 : Symbol(opt1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 18, 13)) +>zip1 : Symbol(Option.zip1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 28)) +>opt2 : Symbol(opt2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 19, 13)) +>opt3 : Symbol(opt3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 20, 13)) + +const zipped2 = opt1.zip2(opt2, opt3); +>zipped2 : Symbol(zipped2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 23, 5)) +>opt1.zip2 : Symbol(Option.zip2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 88)) +>opt1 : Symbol(opt1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 18, 13)) +>zip2 : Symbol(Option.zip2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 2, 88)) +>opt2 : Symbol(opt2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 19, 13)) +>opt3 : Symbol(opt3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 20, 13)) + +const zipped3 = opt1.zip3(opt2, opt3); +>zipped3 : Symbol(zipped3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 24, 5)) +>opt1.zip3 : Symbol(Option.zip3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 88)) +>opt1 : Symbol(opt1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 18, 13)) +>zip3 : Symbol(Option.zip3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 4, 88)) +>opt2 : Symbol(opt2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 19, 13)) +>opt3 : Symbol(opt3, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 20, 13)) + diff --git a/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.types b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.types new file mode 100644 index 0000000000000..1d62458787003 --- /dev/null +++ b/tests/baselines/reference/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.types @@ -0,0 +1,66 @@ +=== tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts === +export {} +export interface Option { + zip1>>(...others: O): Option<[T, ...UnzipOptionArray1]>; +>zip1 : []>(...others: O) => Option<[T, ...UnzipOptionArray1]> +>others : O + + zip2>>(...others: O): Option<[T, ...UnzipOptionArray2]>; +>zip2 : []>(...others: O) => Option<[T, ...UnzipOptionArray2]> +>others : O + + zip3>>(...others: O): Option<[T, ...UnzipOptionArray3]>; +>zip3 : []>(...others: O) => Option<[T, ...UnzipOptionArray3]> +>others : O +} + +type UnzipOption = T extends Option ? V : never; +>UnzipOption : UnzipOption + +/// This doesn't work +type UnzipOptionArray1 = { [k in keyof T]: T[k] extends Option ? UnzipOption : never }; +>UnzipOptionArray1 : UnzipOptionArray1 + +/// But these work +type UnzipOptionArray2 = { [k in keyof T]: UnzipOption }; +>UnzipOptionArray2 : UnzipOptionArray2 + +type UnzipOptionArray3 = { [k in keyof T]: T[k] extends Option ? V : never }; +>UnzipOptionArray3 : UnzipOptionArray3 + +declare const opt1: Option; +>opt1 : Option + +declare const opt2: Option; +>opt2 : Option + +declare const opt3: Option; +>opt3 : Option + +const zipped1 = opt1.zip1(opt2, opt3); +>zipped1 : Option<[number, string, boolean]> +>opt1.zip1(opt2, opt3) : Option<[number, string, boolean]> +>opt1.zip1 : []>(...others: O) => Option<[number, ...UnzipOptionArray1]> +>opt1 : Option +>zip1 : []>(...others: O) => Option<[number, ...UnzipOptionArray1]> +>opt2 : Option +>opt3 : Option + +const zipped2 = opt1.zip2(opt2, opt3); +>zipped2 : Option<[number, string, boolean]> +>opt1.zip2(opt2, opt3) : Option<[number, string, boolean]> +>opt1.zip2 : []>(...others: O) => Option<[number, ...UnzipOptionArray2]> +>opt1 : Option +>zip2 : []>(...others: O) => Option<[number, ...UnzipOptionArray2]> +>opt2 : Option +>opt3 : Option + +const zipped3 = opt1.zip3(opt2, opt3); +>zipped3 : Option<[number, string, boolean]> +>opt1.zip3(opt2, opt3) : Option<[number, string, boolean]> +>opt1.zip3 : []>(...others: O) => Option<[number, ...UnzipOptionArray3]> +>opt1 : Option +>zip3 : []>(...others: O) => Option<[number, ...UnzipOptionArray3]> +>opt2 : Option +>opt3 : Option + diff --git a/tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts b/tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts new file mode 100644 index 0000000000000..f6d67bb361c02 --- /dev/null +++ b/tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts @@ -0,0 +1,25 @@ +export {} +export interface Option { + zip1>>(...others: O): Option<[T, ...UnzipOptionArray1]>; + + zip2>>(...others: O): Option<[T, ...UnzipOptionArray2]>; + + zip3>>(...others: O): Option<[T, ...UnzipOptionArray3]>; +} + +type UnzipOption = T extends Option ? V : never; + +/// This doesn't work +type UnzipOptionArray1 = { [k in keyof T]: T[k] extends Option ? UnzipOption : never }; + +/// But these work +type UnzipOptionArray2 = { [k in keyof T]: UnzipOption }; +type UnzipOptionArray3 = { [k in keyof T]: T[k] extends Option ? V : never }; + +declare const opt1: Option; +declare const opt2: Option; +declare const opt3: Option; + +const zipped1 = opt1.zip1(opt2, opt3); +const zipped2 = opt1.zip2(opt2, opt3); +const zipped3 = opt1.zip3(opt2, opt3); \ No newline at end of file