Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove carve-out in conditional type instantiation that hopefully has been rendered unneeded #51151

Merged
merged 1 commit into from Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/compiler/checker.ts
Expand Up @@ -16374,11 +16374,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.
Expand Down
@@ -0,0 +1,33 @@
//// [recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts]
export {}
export interface Option<T> {
zip1<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray1<O>]>;

zip2<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray2<O>]>;

zip3<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray3<O>]>;
}

type UnzipOption<T> = T extends Option<infer V> ? V : never;

/// This doesn't work
type UnzipOptionArray1<T> = { [k in keyof T]: T[k] extends Option<any> ? UnzipOption<T[k]> : never };

/// But these work
type UnzipOptionArray2<T> = { [k in keyof T]: UnzipOption<T[k]> };
type UnzipOptionArray3<T> = { [k in keyof T]: T[k] extends Option<infer V> ? V : never };

declare const opt1: Option<number>;
declare const opt2: Option<string>;
declare const opt3: Option<boolean>;

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);
@@ -0,0 +1,121 @@
=== tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts ===
export {}
export interface Option<T> {
>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9))
>T : Symbol(T, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 1, 24))

zip1<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray1<O>]>;
>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<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray2<O>]>;
>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<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray3<O>]>;
>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> = T extends Option<infer V> ? 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<T> = { [k in keyof T]: T[k] extends Option<any> ? UnzipOption<T[k]> : 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<T> = { [k in keyof T]: UnzipOption<T[k]> };
>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<T> = { [k in keyof T]: T[k] extends Option<infer V> ? 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<number>;
>opt1 : Symbol(opt1, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 18, 13))
>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9))

declare const opt2: Option<string>;
>opt2 : Symbol(opt2, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 19, 13))
>Option : Symbol(Option, Decl(recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts, 0, 9))

declare const opt3: Option<boolean>;
>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))

@@ -0,0 +1,66 @@
=== tests/cases/compiler/recursiveTypeAliasWithSpreadConditionalReturnNotCircular.ts ===
export {}
export interface Option<T> {
zip1<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray1<O>]>;
>zip1 : <O extends Option<any>[]>(...others: O) => Option<[T, ...UnzipOptionArray1<O>]>
>others : O

zip2<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray2<O>]>;
>zip2 : <O extends Option<any>[]>(...others: O) => Option<[T, ...UnzipOptionArray2<O>]>
>others : O

zip3<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray3<O>]>;
>zip3 : <O extends Option<any>[]>(...others: O) => Option<[T, ...UnzipOptionArray3<O>]>
>others : O
}

type UnzipOption<T> = T extends Option<infer V> ? V : never;
>UnzipOption : UnzipOption<T>

/// This doesn't work
type UnzipOptionArray1<T> = { [k in keyof T]: T[k] extends Option<any> ? UnzipOption<T[k]> : never };
>UnzipOptionArray1 : UnzipOptionArray1<T>

/// But these work
type UnzipOptionArray2<T> = { [k in keyof T]: UnzipOption<T[k]> };
>UnzipOptionArray2 : UnzipOptionArray2<T>

type UnzipOptionArray3<T> = { [k in keyof T]: T[k] extends Option<infer V> ? V : never };
>UnzipOptionArray3 : UnzipOptionArray3<T>

declare const opt1: Option<number>;
>opt1 : Option<number>

declare const opt2: Option<string>;
>opt2 : Option<string>

declare const opt3: Option<boolean>;
>opt3 : Option<boolean>

const zipped1 = opt1.zip1(opt2, opt3);
>zipped1 : Option<[number, string, boolean]>
>opt1.zip1(opt2, opt3) : Option<[number, string, boolean]>
>opt1.zip1 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray1<O>]>
>opt1 : Option<number>
>zip1 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray1<O>]>
>opt2 : Option<string>
>opt3 : Option<boolean>

const zipped2 = opt1.zip2(opt2, opt3);
>zipped2 : Option<[number, string, boolean]>
>opt1.zip2(opt2, opt3) : Option<[number, string, boolean]>
>opt1.zip2 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray2<O>]>
>opt1 : Option<number>
>zip2 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray2<O>]>
>opt2 : Option<string>
>opt3 : Option<boolean>

const zipped3 = opt1.zip3(opt2, opt3);
>zipped3 : Option<[number, string, boolean]>
>opt1.zip3(opt2, opt3) : Option<[number, string, boolean]>
>opt1.zip3 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray3<O>]>
>opt1 : Option<number>
>zip3 : <O extends Option<any>[]>(...others: O) => Option<[number, ...UnzipOptionArray3<O>]>
>opt2 : Option<string>
>opt3 : Option<boolean>

@@ -0,0 +1,25 @@
export {}
export interface Option<T> {
zip1<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray1<O>]>;

zip2<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray2<O>]>;

zip3<O extends Array<Option<any>>>(...others: O): Option<[T, ...UnzipOptionArray3<O>]>;
}

type UnzipOption<T> = T extends Option<infer V> ? V : never;

/// This doesn't work
type UnzipOptionArray1<T> = { [k in keyof T]: T[k] extends Option<any> ? UnzipOption<T[k]> : never };

/// But these work
type UnzipOptionArray2<T> = { [k in keyof T]: UnzipOption<T[k]> };
type UnzipOptionArray3<T> = { [k in keyof T]: T[k] extends Option<infer V> ? V : never };

declare const opt1: Option<number>;
declare const opt2: Option<string>;
declare const opt3: Option<boolean>;

const zipped1 = opt1.zip1(opt2, opt3);
const zipped2 = opt1.zip2(opt2, opt3);
const zipped3 = opt1.zip3(opt2, opt3);