diff --git a/tests/baselines/reference/infiniteConstraints.errors.txt b/tests/baselines/reference/infiniteConstraints.errors.txt new file mode 100644 index 0000000000..108c369378 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.errors.txt @@ -0,0 +1,45 @@ +tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' cannot be used to index type 'B[Exclude]'. +tests/cases/compiler/infiniteConstraints.ts(31,42): error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. + Types of property 'main' are incompatible. + Type 'Record<"val", "dup">' is not assignable to type 'never'. + + +==== tests/cases/compiler/infiniteConstraints.ts (2 errors) ==== + // Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + + type T1], { val: string }>["val"] }> = B; + type T2]["val"] }> = B; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type '"val"' cannot be used to index type 'B[Exclude]'. + + // Repros from #22950 + + type AProp = T + + declare function myBug< + T extends { [K in keyof T]: T[K] extends AProp ? U : never } + >(arg: T): T + + const out = myBug({obj1: {a: "test"}}) + + type Value = Record<"val", V>; + declare function value(val: V): Value; + + declare function ensureNoDuplicates< + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } + >(vals: T): void; + + const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); + + const shouldBeNoError = ensureNoDuplicates({main: value("test")}); + + const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ main: Record<"val", "dup">; alternate: Record<"val", "dup">; }' is not assignable to parameter of type '{ main: never; alternate: never; }'. +!!! error TS2345: Types of property 'main' are incompatible. +!!! error TS2345: Type 'Record<"val", "dup">' is not assignable to type 'never'. + \ No newline at end of file diff --git a/tests/baselines/reference/infiniteConstraints.js b/tests/baselines/reference/infiniteConstraints.js new file mode 100644 index 0000000000..0ad3b676f1 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.js @@ -0,0 +1,41 @@ +//// [infiniteConstraints.ts] +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +type T2]["val"] }> = B; + +// Repros from #22950 + +type AProp = T + +declare function myBug< + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>(arg: T): T + +const out = myBug({obj1: {a: "test"}}) + +type Value = Record<"val", V>; +declare function value(val: V): Value; + +declare function ensureNoDuplicates< + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } +>(vals: T): void; + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); + + +//// [infiniteConstraints.js] +"use strict"; +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint +var out = myBug({ obj1: { a: "test" } }); +var noError = ensureNoDuplicates({ main: value("test"), alternate: value("test2") }); +var shouldBeNoError = ensureNoDuplicates({ main: value("test") }); +var shouldBeError = ensureNoDuplicates({ main: value("dup"), alternate: value("dup") }); diff --git a/tests/baselines/reference/infiniteConstraints.symbols b/tests/baselines/reference/infiniteConstraints.symbols new file mode 100644 index 0000000000..0f0d44c9f5 --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.symbols @@ -0,0 +1,122 @@ +=== tests/cases/compiler/infiniteConstraints.ts === +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +>T1 : Symbol(T1, Decl(infiniteConstraints.ts, 0, 0)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 2, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 2, 21)) +>val : Symbol(val, Decl(infiniteConstraints.ts, 2, 69)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 2, 8)) + +type T2]["val"] }> = B; +>T2 : Symbol(T2, Decl(infiniteConstraints.ts, 2, 99)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 3, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 3, 21)) +>B : Symbol(B, Decl(infiniteConstraints.ts, 3, 8)) + +// Repros from #22950 + +type AProp = T +>AProp : Symbol(AProp, Decl(infiniteConstraints.ts, 3, 73)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 7, 11)) +>a : Symbol(a, Decl(infiniteConstraints.ts, 7, 22)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 7, 11)) + +declare function myBug< +>myBug : Symbol(myBug, Decl(infiniteConstraints.ts, 7, 39)) + + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 10, 15)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 10, 15)) +>AProp : Symbol(AProp, Decl(infiniteConstraints.ts, 3, 73)) +>U : Symbol(U, Decl(infiniteConstraints.ts, 10, 54)) +>U : Symbol(U, Decl(infiniteConstraints.ts, 10, 54)) + +>(arg: T): T +>arg : Symbol(arg, Decl(infiniteConstraints.ts, 11, 2)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 9, 23)) + +const out = myBug({obj1: {a: "test"}}) +>out : Symbol(out, Decl(infiniteConstraints.ts, 13, 5)) +>myBug : Symbol(myBug, Decl(infiniteConstraints.ts, 7, 39)) +>obj1 : Symbol(obj1, Decl(infiniteConstraints.ts, 13, 19)) +>a : Symbol(a, Decl(infiniteConstraints.ts, 13, 26)) + +type Value = Record<"val", V>; +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 15, 11)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 15, 11)) + +declare function value(val: V): Value; +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) +>val : Symbol(val, Decl(infiniteConstraints.ts, 16, 41)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>V : Symbol(V, Decl(infiniteConstraints.ts, 16, 23)) + +declare function ensureNoDuplicates< +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) + + T extends { +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) + + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) +>K : Symbol(K, Decl(infiniteConstraints.ts, 20, 5)) +>Value : Symbol(Value, Decl(infiniteConstraints.ts, 13, 38)) + + ? never + : any + } +>(vals: T): void; +>vals : Symbol(vals, Decl(infiniteConstraints.ts, 24, 2)) +>T : Symbol(T, Decl(infiniteConstraints.ts, 18, 36)) + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); +>noError : Symbol(noError, Decl(infiniteConstraints.ts, 26, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 26, 36)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>alternate : Symbol(alternate, Decl(infiniteConstraints.ts, 26, 56)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); +>shouldBeNoError : Symbol(shouldBeNoError, Decl(infiniteConstraints.ts, 28, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 28, 44)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); +>shouldBeError : Symbol(shouldBeError, Decl(infiniteConstraints.ts, 30, 5)) +>ensureNoDuplicates : Symbol(ensureNoDuplicates, Decl(infiniteConstraints.ts, 16, 59)) +>main : Symbol(main, Decl(infiniteConstraints.ts, 30, 42)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) +>alternate : Symbol(alternate, Decl(infiniteConstraints.ts, 30, 61)) +>value : Symbol(value, Decl(infiniteConstraints.ts, 15, 57)) + diff --git a/tests/baselines/reference/infiniteConstraints.types b/tests/baselines/reference/infiniteConstraints.types new file mode 100644 index 0000000000..78fbc9beca --- /dev/null +++ b/tests/baselines/reference/infiniteConstraints.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/infiniteConstraints.ts === +// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint + +type T1], { val: string }>["val"] }> = B; +>T1 : B +>val : string + +type T2]["val"] }> = B; +>T2 : B + +// Repros from #22950 + +type AProp = T +>AProp : T +>a : string + +declare function myBug< +>myBug : (arg: T) => T + + T extends { [K in keyof T]: T[K] extends AProp ? U : never } +>(arg: T): T +>arg : T + +const out = myBug({obj1: {a: "test"}}) +>out : { obj1: { a: string; }; } +>myBug({obj1: {a: "test"}}) : { obj1: { a: string; }; } +>myBug : (arg: T) => T +>{obj1: {a: "test"}} : { obj1: { a: string; }; } +>obj1 : { a: string; } +>{a: "test"} : { a: string; } +>a : string +>"test" : "test" + +type Value = Record<"val", V>; +>Value : Record<"val", V> + +declare function value(val: V): Value; +>value : (val: V) => Record<"val", V> +>val : V + +declare function ensureNoDuplicates< +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void + + T extends { + [K in keyof T]: Extract["val"] extends Extract], Value>["val"] + ? never + : any + } +>(vals: T): void; +>vals : T + +const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")}); +>noError : void +>ensureNoDuplicates({main: value("test"), alternate: value("test2")}) : void +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("test"), alternate: value("test2")} : { main: Record<"val", "test">; alternate: Record<"val", "test2">; } +>main : Record<"val", "test"> +>value("test") : Record<"val", "test"> +>value : (val: V) => Record<"val", V> +>"test" : "test" +>alternate : Record<"val", "test2"> +>value("test2") : Record<"val", "test2"> +>value : (val: V) => Record<"val", V> +>"test2" : "test2" + +const shouldBeNoError = ensureNoDuplicates({main: value("test")}); +>shouldBeNoError : void +>ensureNoDuplicates({main: value("test")}) : void +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("test")} : { main: Record<"val", "test">; } +>main : Record<"val", "test"> +>value("test") : Record<"val", "test"> +>value : (val: V) => Record<"val", V> +>"test" : "test" + +const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")}); +>shouldBeError : any +>ensureNoDuplicates({main: value("dup"), alternate: value("dup")}) : any +>ensureNoDuplicates : >["val"] extends Extract], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void +>{main: value("dup"), alternate: value("dup")} : { main: Record<"val", "dup">; alternate: Record<"val", "dup">; } +>main : Record<"val", "dup"> +>value("dup") : Record<"val", "dup"> +>value : (val: V) => Record<"val", V> +>"dup" : "dup" +>alternate : Record<"val", "dup"> +>value("dup") : Record<"val", "dup"> +>value : (val: V) => Record<"val", V> +>"dup" : "dup" +