diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfd479127202c..ce36e63271de8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17225,7 +17225,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } node = parent; } - return constraints ? getSubstitutionType(type, getIntersectionType(constraints)) : type; + if (!constraints) { + return type; + } + if (isNoInferType(type)) { + constraints = append(constraints, (type as SubstitutionType).baseType); + return getNoInferType(getIntersectionType(constraints)); + } + return getSubstitutionType(type, getIntersectionType(constraints)); } function isJSDocTypeReference(node: Node): node is TypeReferenceNode { diff --git a/tests/baselines/reference/noInferSubstitutionTypes1.errors.txt b/tests/baselines/reference/noInferSubstitutionTypes1.errors.txt new file mode 100644 index 0000000000000..570d4392b2874 --- /dev/null +++ b/tests/baselines/reference/noInferSubstitutionTypes1.errors.txt @@ -0,0 +1,42 @@ +noInferSubstitutionTypes1.ts(4,24): error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. +noInferSubstitutionTypes1.ts(7,25): error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. +noInferSubstitutionTypes1.ts(10,25): error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. +noInferSubstitutionTypes1.ts(13,26): error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. +noInferSubstitutionTypes1.ts(16,27): error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. +noInferSubstitutionTypes1.ts(20,27): error TS2345: Argument of type '42' is not assignable to parameter of type '"foo"'. + + +==== noInferSubstitutionTypes1.ts (6 errors) ==== + // https://github.com/microsoft/TypeScript/issues/59826 + + declare function g(a: A, b: A extends string ? `rel:${NoInfer}` : never): A; + const result1 = g("5", "rel:7"); // error + ~~~~~~~ +!!! error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. + + declare function g2(a: A, b: A extends string ? NoInfer<`rel:${A}`> : never): A; + const result2 = g2("5", "rel:7"); // error + ~~~~~~~ +!!! error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. + + declare function g3(a: A, b: NoInfer): A; + const result3 = g3("5", "rel:7"); // error + ~~~~~~~ +!!! error TS2345: Argument of type '"rel:7"' is not assignable to parameter of type '"rel:5"'. + + declare function h(a: A, b: A extends string ? NoInfer : never): A; + const result4 = h("foo", "bar"); // error + ~~~~~ +!!! error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. + + declare function h2(a: A, b: NoInfer extends string ? NoInfer : never): A; + const result5 = h2("foo", "bar"); // error + ~~~~~ +!!! error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. + + declare function h3(a: A, b: NoInfer extends string ? A : never): A; + const result6 = h3("foo", "bar"); // no error + const result7 = h3("foo", 42); // error + ~~ +!!! error TS2345: Argument of type '42' is not assignable to parameter of type '"foo"'. + \ No newline at end of file diff --git a/tests/baselines/reference/noInferSubstitutionTypes1.symbols b/tests/baselines/reference/noInferSubstitutionTypes1.symbols new file mode 100644 index 0000000000000..7ebf78e9644f7 --- /dev/null +++ b/tests/baselines/reference/noInferSubstitutionTypes1.symbols @@ -0,0 +1,100 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferSubstitutionTypes1.ts] //// + +=== noInferSubstitutionTypes1.ts === +// https://github.com/microsoft/TypeScript/issues/59826 + +declare function g(a: A, b: A extends string ? `rel:${NoInfer}` : never): A; +>g : Symbol(g, Decl(noInferSubstitutionTypes1.ts, 0, 0)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 2, 19)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 2, 22)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 2, 19)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 2, 27)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 2, 19)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 2, 19)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 2, 19)) + +const result1 = g("5", "rel:7"); // error +>result1 : Symbol(result1, Decl(noInferSubstitutionTypes1.ts, 3, 5)) +>g : Symbol(g, Decl(noInferSubstitutionTypes1.ts, 0, 0)) + +declare function g2(a: A, b: A extends string ? NoInfer<`rel:${A}`> : never): A; +>g2 : Symbol(g2, Decl(noInferSubstitutionTypes1.ts, 3, 32)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 5, 20)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 5, 23)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 5, 20)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 5, 28)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 5, 20)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 5, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 5, 20)) + +const result2 = g2("5", "rel:7"); // error +>result2 : Symbol(result2, Decl(noInferSubstitutionTypes1.ts, 6, 5)) +>g2 : Symbol(g2, Decl(noInferSubstitutionTypes1.ts, 3, 32)) + +declare function g3(a: A, b: NoInfer): A; +>g3 : Symbol(g3, Decl(noInferSubstitutionTypes1.ts, 6, 33)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 8, 20)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 8, 23)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 8, 20)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 8, 28)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 8, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 8, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 8, 20)) + +const result3 = g3("5", "rel:7"); // error +>result3 : Symbol(result3, Decl(noInferSubstitutionTypes1.ts, 9, 5)) +>g3 : Symbol(g3, Decl(noInferSubstitutionTypes1.ts, 6, 33)) + +declare function h(a: A, b: A extends string ? NoInfer : never): A; +>h : Symbol(h, Decl(noInferSubstitutionTypes1.ts, 9, 33)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 11, 19)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 11, 28)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 11, 19)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 11, 33)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 11, 19)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 11, 19)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 11, 19)) + +const result4 = h("foo", "bar"); // error +>result4 : Symbol(result4, Decl(noInferSubstitutionTypes1.ts, 12, 5)) +>h : Symbol(h, Decl(noInferSubstitutionTypes1.ts, 9, 33)) + +declare function h2(a: A, b: NoInfer extends string ? NoInfer : never): A; +>h2 : Symbol(h2, Decl(noInferSubstitutionTypes1.ts, 12, 32)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 14, 20)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 14, 29)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 14, 20)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 14, 34)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 14, 20)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 14, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 14, 20)) + +const result5 = h2("foo", "bar"); // error +>result5 : Symbol(result5, Decl(noInferSubstitutionTypes1.ts, 15, 5)) +>h2 : Symbol(h2, Decl(noInferSubstitutionTypes1.ts, 12, 32)) + +declare function h3(a: A, b: NoInfer extends string ? A : never): A; +>h3 : Symbol(h3, Decl(noInferSubstitutionTypes1.ts, 15, 33)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 17, 20)) +>a : Symbol(a, Decl(noInferSubstitutionTypes1.ts, 17, 29)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 17, 20)) +>b : Symbol(b, Decl(noInferSubstitutionTypes1.ts, 17, 34)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 17, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 17, 20)) +>A : Symbol(A, Decl(noInferSubstitutionTypes1.ts, 17, 20)) + +const result6 = h3("foo", "bar"); // no error +>result6 : Symbol(result6, Decl(noInferSubstitutionTypes1.ts, 18, 5)) +>h3 : Symbol(h3, Decl(noInferSubstitutionTypes1.ts, 15, 33)) + +const result7 = h3("foo", 42); // error +>result7 : Symbol(result7, Decl(noInferSubstitutionTypes1.ts, 19, 5)) +>h3 : Symbol(h3, Decl(noInferSubstitutionTypes1.ts, 15, 33)) + diff --git a/tests/baselines/reference/noInferSubstitutionTypes1.types b/tests/baselines/reference/noInferSubstitutionTypes1.types new file mode 100644 index 0000000000000..5945c0a51c510 --- /dev/null +++ b/tests/baselines/reference/noInferSubstitutionTypes1.types @@ -0,0 +1,137 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferSubstitutionTypes1.ts] //// + +=== noInferSubstitutionTypes1.ts === +// https://github.com/microsoft/TypeScript/issues/59826 + +declare function g(a: A, b: A extends string ? `rel:${NoInfer}` : never): A; +>g : (a: A, b: A extends string ? `rel:${NoInfer}` : never) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : A extends string ? `rel:${NoInfer}` : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result1 = g("5", "rel:7"); // error +>result1 : "5" +> : ^^^ +>g("5", "rel:7") : "5" +> : ^^^ +>g : (a: A, b: A extends string ? `rel:${NoInfer}` : never) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>"5" : "5" +> : ^^^ +>"rel:7" : "rel:7" +> : ^^^^^^^ + +declare function g2(a: A, b: A extends string ? NoInfer<`rel:${A}`> : never): A; +>g2 : (a: A, b: A extends string ? NoInfer<`rel:${A}`> : never) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : A extends string ? NoInfer<`rel:${A}`> : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result2 = g2("5", "rel:7"); // error +>result2 : "5" +> : ^^^ +>g2("5", "rel:7") : "5" +> : ^^^ +>g2 : (a: A, b: A extends string ? NoInfer<`rel:${A}`> : never) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>"5" : "5" +> : ^^^ +>"rel:7" : "rel:7" +> : ^^^^^^^ + +declare function g3(a: A, b: NoInfer): A; +>g3 : (a: A, b: NoInfer) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : NoInfer +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result3 = g3("5", "rel:7"); // error +>result3 : "5" +> : ^^^ +>g3("5", "rel:7") : "5" +> : ^^^ +>g3 : (a: A, b: NoInfer) => A +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>"5" : "5" +> : ^^^ +>"rel:7" : "rel:7" +> : ^^^^^^^ + +declare function h(a: A, b: A extends string ? NoInfer : never): A; +>h : (a: A, b: A extends string ? NoInfer : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : A extends string ? NoInfer : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result4 = h("foo", "bar"); // error +>result4 : "foo" +> : ^^^^^ +>h("foo", "bar") : "foo" +> : ^^^^^ +>h : (a: A, b: A extends string ? NoInfer : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>"bar" : "bar" +> : ^^^^^ + +declare function h2(a: A, b: NoInfer extends string ? NoInfer : never): A; +>h2 : (a: A, b: NoInfer extends string ? NoInfer : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : NoInfer extends string ? NoInfer : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result5 = h2("foo", "bar"); // error +>result5 : "foo" +> : ^^^^^ +>h2("foo", "bar") : "foo" +> : ^^^^^ +>h2 : (a: A, b: NoInfer extends string ? NoInfer : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>"bar" : "bar" +> : ^^^^^ + +declare function h3(a: A, b: NoInfer extends string ? A : never): A; +>h3 : (a: A, b: NoInfer extends string ? A : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : A +> : ^ +>b : NoInfer extends string ? A : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const result6 = h3("foo", "bar"); // no error +>result6 : "foo" | "bar" +> : ^^^^^^^^^^^^^ +>h3("foo", "bar") : "foo" | "bar" +> : ^^^^^^^^^^^^^ +>h3 : (a: A, b: NoInfer extends string ? A : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>"bar" : "bar" +> : ^^^^^ + +const result7 = h3("foo", 42); // error +>result7 : "foo" +> : ^^^^^ +>h3("foo", 42) : "foo" +> : ^^^^^ +>h3 : (a: A, b: NoInfer extends string ? A : never) => A +> : ^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>42 : 42 +> : ^^ + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInferSubstitutionTypes1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInferSubstitutionTypes1.ts new file mode 100644 index 0000000000000..21a26e30ef637 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInferSubstitutionTypes1.ts @@ -0,0 +1,23 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/59826 + +declare function g(a: A, b: A extends string ? `rel:${NoInfer}` : never): A; +const result1 = g("5", "rel:7"); // error + +declare function g2(a: A, b: A extends string ? NoInfer<`rel:${A}`> : never): A; +const result2 = g2("5", "rel:7"); // error + +declare function g3(a: A, b: NoInfer): A; +const result3 = g3("5", "rel:7"); // error + +declare function h(a: A, b: A extends string ? NoInfer : never): A; +const result4 = h("foo", "bar"); // error + +declare function h2(a: A, b: NoInfer extends string ? NoInfer : never): A; +const result5 = h2("foo", "bar"); // error + +declare function h3(a: A, b: NoInfer extends string ? A : never): A; +const result6 = h3("foo", "bar"); // no error +const result7 = h3("foo", 42); // error