From a668b6b19bbd52b546d3b34a897700316274b715 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Tue, 4 Feb 2025 13:22:26 -0800 Subject: [PATCH 1/2] allow extends type to be supertype of constraint types --- src/compiler/checker.ts | 4 +- .../reference/dependentReturnType1.errors.txt | 8 +- .../dependentReturnType10.errors.txt | 41 ++++++ .../reference/dependentReturnType10.symbols | 100 ++++++++++++++ .../reference/dependentReturnType10.types | 128 ++++++++++++++++++ tests/cases/compiler/dependentReturnType10.ts | 37 +++++ 6 files changed, 309 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/dependentReturnType10.errors.txt create mode 100644 tests/baselines/reference/dependentReturnType10.symbols create mode 100644 tests/baselines/reference/dependentReturnType10.types create mode 100644 tests/cases/compiler/dependentReturnType10.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcb93c45dc1dd..b1b5dacd450ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -46082,7 +46082,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // (0) The conditional type is distributive; // (1) The conditional type has no `infer` type parameters; // (2) The conditional type's check type is a narrowable type parameter (i.e. a type parameter with a union constraint); - // (3) The extends type `A` is a type or a union of types belonging to the union constraint of the type parameter; + // (3) The extends type `A` is a type or a union of types that are supertypes of the union constraint of the type parameter; // (4) `TrueBranch` and `FalseBranch` must be valid, recursively. // In particular, the false-most branch of the conditional type must be `never`. function isNarrowableConditionalTypeWorker(type: ConditionalType): boolean { @@ -46111,7 +46111,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !everyType(type.extendsType, extendsType => some( (constraintType as UnionType).types, - constraintType => isTypeIdenticalTo(constraintType, extendsType), + constraintType => isTypeAssignableTo(constraintType, extendsType), )) ) { return false; diff --git a/tests/baselines/reference/dependentReturnType1.errors.txt b/tests/baselines/reference/dependentReturnType1.errors.txt index 4513ccb75cf29..eaffd76cfbad5 100644 --- a/tests/baselines/reference/dependentReturnType1.errors.txt +++ b/tests/baselines/reference/dependentReturnType1.errors.txt @@ -26,8 +26,6 @@ dependentReturnType1.ts(275,9): error TS2322: Type '1' is not assignable to type dependentReturnType1.ts(278,9): error TS2322: Type '2' is not assignable to type 'HelperCond<{ x: U; y: V; }, { x: string; y: true; }, 1, { x: number; y: false; }, 2>'. dependentReturnType1.ts(280,5): error TS2322: Type '0' is not assignable to type 'HelperCond<{ x: U; y: V; }, { x: string; y: true; }, 1, { x: number; y: false; }, 2>'. dependentReturnType1.ts(302,9): error TS2322: Type 'string' is not assignable to type 'string[]'. -dependentReturnType1.ts(311,9): error TS2322: Type 'undefined' is not assignable to type 'T extends {} ? void : T extends undefined ? number : never'. -dependentReturnType1.ts(313,5): error TS2322: Type 'number' is not assignable to type 'T extends {} ? void : T extends undefined ? number : never'. dependentReturnType1.ts(334,9): error TS2322: Type '1' is not assignable to type '4'. dependentReturnType1.ts(367,13): error TS2322: Type 'number' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. dependentReturnType1.ts(369,9): error TS2322: Type 'string' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. @@ -44,7 +42,7 @@ dependentReturnType1.ts(488,9): error TS2322: Type 'R' is not assignable to type dependentReturnType1.ts(514,5): error TS2322: Type '1' is not assignable to type 'never'. -==== dependentReturnType1.ts (39 errors) ==== +==== dependentReturnType1.ts (37 errors) ==== interface A { 1: number; 2: string; @@ -407,12 +405,8 @@ dependentReturnType1.ts(514,5): error TS2322: Type '1' is not assignable to type ): T extends {} ? void : T extends undefined ? number : never { if (x) { return; - ~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'T extends {} ? void : T extends undefined ? number : never'. } return 1; - ~~~~~~ -!!! error TS2322: Type 'number' is not assignable to type 'T extends {} ? void : T extends undefined ? number : never'. } // Multiple type parameters at once diff --git a/tests/baselines/reference/dependentReturnType10.errors.txt b/tests/baselines/reference/dependentReturnType10.errors.txt new file mode 100644 index 0000000000000..c4f2d23efafcb --- /dev/null +++ b/tests/baselines/reference/dependentReturnType10.errors.txt @@ -0,0 +1,41 @@ +dependentReturnType10.ts(29,9): error TS2322: Type 'number' is not assignable to type 'void'. + + +==== dependentReturnType10.ts (1 errors) ==== + interface Animal { + name: string; + species: string; + } + + interface Dog extends Animal { + breed: string; + } + + type GreetRet = + T extends string ? string : + T extends { name: string } ? { greeting: string, breed: string } : + never; + + function greet(animal: T): GreetRet { + if (typeof animal === "string") { + return `hello, ${animal}` + } + return { greeting: `woof, ${animal.name}`, breed: animal.breed } + } + + type BadRet = + T extends {} ? void : + T extends string ? number : + never; + + function badFun(x: T): BadRet { + if (typeof x === "string") { + return 1 + ~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'void'. + } + return; + } + + declare let arg2: { a: string } | string; + const badRet = badFun(arg2); \ No newline at end of file diff --git a/tests/baselines/reference/dependentReturnType10.symbols b/tests/baselines/reference/dependentReturnType10.symbols new file mode 100644 index 0000000000000..6715843da1b11 --- /dev/null +++ b/tests/baselines/reference/dependentReturnType10.symbols @@ -0,0 +1,100 @@ +//// [tests/cases/compiler/dependentReturnType10.ts] //// + +=== dependentReturnType10.ts === +interface Animal { +>Animal : Symbol(Animal, Decl(dependentReturnType10.ts, 0, 0)) + + name: string; +>name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18)) + + species: string; +>species : Symbol(Animal.species, Decl(dependentReturnType10.ts, 1, 17)) +} + +interface Dog extends Animal { +>Dog : Symbol(Dog, Decl(dependentReturnType10.ts, 3, 1)) +>Animal : Symbol(Animal, Decl(dependentReturnType10.ts, 0, 0)) + + breed: string; +>breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30)) +} + +type GreetRet = +>GreetRet : Symbol(GreetRet, Decl(dependentReturnType10.ts, 7, 1)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14)) + + T extends string ? string : +>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14)) + + T extends { name: string } ? { greeting: string, breed: string } : +>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14)) +>name : Symbol(name, Decl(dependentReturnType10.ts, 11, 15)) +>greeting : Symbol(greeting, Decl(dependentReturnType10.ts, 11, 34)) +>breed : Symbol(breed, Decl(dependentReturnType10.ts, 11, 52)) + + never; + +function greet(animal: T): GreetRet { +>greet : Symbol(greet, Decl(dependentReturnType10.ts, 12, 10)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15)) +>Dog : Symbol(Dog, Decl(dependentReturnType10.ts, 3, 1)) +>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15)) +>GreetRet : Symbol(GreetRet, Decl(dependentReturnType10.ts, 7, 1)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15)) + + if (typeof animal === "string") { +>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39)) + + return `hello, ${animal}` +>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39)) + } + return { greeting: `woof, ${animal.name}`, breed: animal.breed } +>greeting : Symbol(greeting, Decl(dependentReturnType10.ts, 18, 12)) +>animal.name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18)) +>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39)) +>name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18)) +>breed : Symbol(breed, Decl(dependentReturnType10.ts, 18, 46)) +>animal.breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30)) +>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39)) +>breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30)) +} + +type BadRet = +>BadRet : Symbol(BadRet, Decl(dependentReturnType10.ts, 19, 1)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 21, 12)) + + T extends {} ? void : +>T : Symbol(T, Decl(dependentReturnType10.ts, 21, 12)) + + T extends string ? number : +>T : Symbol(T, Decl(dependentReturnType10.ts, 21, 12)) + + never; + +function badFun(x: T): BadRet { +>badFun : Symbol(badFun, Decl(dependentReturnType10.ts, 24, 10)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 26, 16)) +>a : Symbol(a, Decl(dependentReturnType10.ts, 26, 27)) +>x : Symbol(x, Decl(dependentReturnType10.ts, 26, 50)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 26, 16)) +>BadRet : Symbol(BadRet, Decl(dependentReturnType10.ts, 19, 1)) +>T : Symbol(T, Decl(dependentReturnType10.ts, 26, 16)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(dependentReturnType10.ts, 26, 50)) + + return 1 + } + return; +} + +declare let arg2: { a: string } | string; +>arg2 : Symbol(arg2, Decl(dependentReturnType10.ts, 33, 11)) +>a : Symbol(a, Decl(dependentReturnType10.ts, 33, 19)) + +const badRet = badFun(arg2); +>badRet : Symbol(badRet, Decl(dependentReturnType10.ts, 34, 5)) +>badFun : Symbol(badFun, Decl(dependentReturnType10.ts, 24, 10)) +>arg2 : Symbol(arg2, Decl(dependentReturnType10.ts, 33, 11)) + diff --git a/tests/baselines/reference/dependentReturnType10.types b/tests/baselines/reference/dependentReturnType10.types new file mode 100644 index 0000000000000..bc813c2855253 --- /dev/null +++ b/tests/baselines/reference/dependentReturnType10.types @@ -0,0 +1,128 @@ +//// [tests/cases/compiler/dependentReturnType10.ts] //// + +=== dependentReturnType10.ts === +interface Animal { + name: string; +>name : string +> : ^^^^^^ + + species: string; +>species : string +> : ^^^^^^ +} + +interface Dog extends Animal { + breed: string; +>breed : string +> : ^^^^^^ +} + +type GreetRet = +>GreetRet : GreetRet +> : ^^^^^^^^^^^ + + T extends string ? string : + T extends { name: string } ? { greeting: string, breed: string } : +>name : string +> : ^^^^^^ +>greeting : string +> : ^^^^^^ +>breed : string +> : ^^^^^^ + + never; + +function greet(animal: T): GreetRet { +>greet : (animal: T) => GreetRet +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>animal : T +> : ^ + + if (typeof animal === "string") { +>typeof animal === "string" : boolean +> : ^^^^^^^ +>typeof animal : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>animal : T +> : ^ +>"string" : "string" +> : ^^^^^^^^ + + return `hello, ${animal}` +>`hello, ${animal}` : string +> : ^^^^^^ +>animal : T & string +> : ^^^^^^^^^^ + } + return { greeting: `woof, ${animal.name}`, breed: animal.breed } +>{ greeting: `woof, ${animal.name}`, breed: animal.breed } : { greeting: string; breed: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>greeting : string +> : ^^^^^^ +>`woof, ${animal.name}` : string +> : ^^^^^^ +>animal.name : string +> : ^^^^^^ +>animal : Dog +> : ^^^ +>name : string +> : ^^^^^^ +>breed : string +> : ^^^^^^ +>animal.breed : string +> : ^^^^^^ +>animal : Dog +> : ^^^ +>breed : string +> : ^^^^^^ +} + +type BadRet = +>BadRet : BadRet +> : ^^^^^^^^^ + + T extends {} ? void : + T extends string ? number : + never; + +function badFun(x: T): BadRet { +>badFun : (x: T) => BadRet +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>a : string +> : ^^^^^^ +>x : T +> : ^ + + if (typeof x === "string") { +>typeof x === "string" : boolean +> : ^^^^^^^ +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>x : T +> : ^ +>"string" : "string" +> : ^^^^^^^^ + + return 1 +>1 : 1 +> : ^ + } + return; +} + +declare let arg2: { a: string } | string; +>arg2 : string | { a: string; } +> : ^^^^^^^^^^^^^^ ^^^ +>a : string +> : ^^^^^^ + +const badRet = badFun(arg2); +>badRet : void +> : ^^^^ +>badFun(arg2) : void +> : ^^^^ +>badFun : (x: T) => BadRet +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>arg2 : string | { a: string; } +> : ^^^^^^^^^^^^^^ ^^^ + diff --git a/tests/cases/compiler/dependentReturnType10.ts b/tests/cases/compiler/dependentReturnType10.ts new file mode 100644 index 0000000000000..4ada38a97dd03 --- /dev/null +++ b/tests/cases/compiler/dependentReturnType10.ts @@ -0,0 +1,37 @@ +// @noEmit: true + +interface Animal { + name: string; + species: string; +} + +interface Dog extends Animal { + breed: string; +} + +type GreetRet = + T extends string ? string : + T extends { name: string } ? { greeting: string, breed: string } : + never; + +function greet(animal: T): GreetRet { + if (typeof animal === "string") { + return `hello, ${animal}` + } + return { greeting: `woof, ${animal.name}`, breed: animal.breed } +} + +type BadRet = + T extends {} ? void : + T extends string ? number : + never; + +function badFun(x: T): BadRet { + if (typeof x === "string") { + return 1 + } + return; +} + +declare let arg2: { a: string } | string; +const badRet = badFun(arg2); \ No newline at end of file From c14044981e427b7d24b93cc08d48df7752f99c6f Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 5 Feb 2025 10:56:22 -0800 Subject: [PATCH 2/2] update comment --- .../reference/dependentReturnType1.errors.txt | 29 +- .../reference/dependentReturnType1.symbols | 469 +++++++++--------- .../reference/dependentReturnType1.types | 1 - tests/cases/compiler/dependentReturnType1.ts | 1 - 4 files changed, 248 insertions(+), 252 deletions(-) diff --git a/tests/baselines/reference/dependentReturnType1.errors.txt b/tests/baselines/reference/dependentReturnType1.errors.txt index eaffd76cfbad5..42315f39ff459 100644 --- a/tests/baselines/reference/dependentReturnType1.errors.txt +++ b/tests/baselines/reference/dependentReturnType1.errors.txt @@ -26,20 +26,20 @@ dependentReturnType1.ts(275,9): error TS2322: Type '1' is not assignable to type dependentReturnType1.ts(278,9): error TS2322: Type '2' is not assignable to type 'HelperCond<{ x: U; y: V; }, { x: string; y: true; }, 1, { x: number; y: false; }, 2>'. dependentReturnType1.ts(280,5): error TS2322: Type '0' is not assignable to type 'HelperCond<{ x: U; y: V; }, { x: string; y: true; }, 1, { x: number; y: false; }, 2>'. dependentReturnType1.ts(302,9): error TS2322: Type 'string' is not assignable to type 'string[]'. -dependentReturnType1.ts(334,9): error TS2322: Type '1' is not assignable to type '4'. -dependentReturnType1.ts(367,13): error TS2322: Type 'number' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. -dependentReturnType1.ts(369,9): error TS2322: Type 'string' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. -dependentReturnType1.ts(392,9): error TS2322: Type '2' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. -dependentReturnType1.ts(402,13): error TS2322: Type 'number' is not assignable to type 'string'. -dependentReturnType1.ts(412,9): error TS2322: Type 'true' is not assignable to type 'T extends [infer R] ? R : T extends number ? boolean : never'. -dependentReturnType1.ts(414,5): error TS2322: Type '""' is not assignable to type 'T extends [infer R] ? R : T extends number ? boolean : never'. -dependentReturnType1.ts(439,15): error TS2322: Type '1' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. -dependentReturnType1.ts(441,11): error TS2322: Type '2' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. -dependentReturnType1.ts(470,13): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. -dependentReturnType1.ts(472,13): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. -dependentReturnType1.ts(474,13): error TS2322: Type 'T' is not assignable to type 'ConditionalReturnType'. -dependentReturnType1.ts(488,9): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. -dependentReturnType1.ts(514,5): error TS2322: Type '1' is not assignable to type 'never'. +dependentReturnType1.ts(333,9): error TS2322: Type '1' is not assignable to type '4'. +dependentReturnType1.ts(366,13): error TS2322: Type 'number' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. +dependentReturnType1.ts(368,9): error TS2322: Type 'string' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : never'. +dependentReturnType1.ts(391,9): error TS2322: Type '2' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. +dependentReturnType1.ts(401,13): error TS2322: Type 'number' is not assignable to type 'string'. +dependentReturnType1.ts(411,9): error TS2322: Type 'true' is not assignable to type 'T extends [infer R] ? R : T extends number ? boolean : never'. +dependentReturnType1.ts(413,5): error TS2322: Type '""' is not assignable to type 'T extends [infer R] ? R : T extends number ? boolean : never'. +dependentReturnType1.ts(438,15): error TS2322: Type '1' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. +dependentReturnType1.ts(440,11): error TS2322: Type '2' is not assignable to type 'T extends true ? 1 : T extends false ? 2 : never'. +dependentReturnType1.ts(469,13): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. +dependentReturnType1.ts(471,13): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. +dependentReturnType1.ts(473,13): error TS2322: Type 'T' is not assignable to type 'ConditionalReturnType'. +dependentReturnType1.ts(487,9): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType'. +dependentReturnType1.ts(513,5): error TS2322: Type '1' is not assignable to type 'never'. ==== dependentReturnType1.ts (37 errors) ==== @@ -399,7 +399,6 @@ dependentReturnType1.ts(514,5): error TS2322: Type '1' is not assignable to type } } - // No narrowing because conditional's extends type is different from type parameter constraint types function voidRet( x: T ): T extends {} ? void : T extends undefined ? number : never { diff --git a/tests/baselines/reference/dependentReturnType1.symbols b/tests/baselines/reference/dependentReturnType1.symbols index 11976eb81c5e6..f7ca36240928c 100644 --- a/tests/baselines/reference/dependentReturnType1.symbols +++ b/tests/baselines/reference/dependentReturnType1.symbols @@ -848,22 +848,21 @@ function badCapitalize( } } -// No narrowing because conditional's extends type is different from type parameter constraint types function voidRet( >voidRet : Symbol(voidRet, Decl(dependentReturnType1.ts, 303, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 306, 17)) ->a : Symbol(a, Decl(dependentReturnType1.ts, 306, 28)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 305, 17)) +>a : Symbol(a, Decl(dependentReturnType1.ts, 305, 28)) x: T ->x : Symbol(x, Decl(dependentReturnType1.ts, 306, 54)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 306, 17)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 305, 54)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 305, 17)) ): T extends {} ? void : T extends undefined ? number : never { ->T : Symbol(T, Decl(dependentReturnType1.ts, 306, 17)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 306, 17)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 305, 17)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 305, 17)) if (x) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 306, 54)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 305, 54)) return; } @@ -872,46 +871,46 @@ function voidRet( // Multiple type parameters at once function woo( ->woo : Symbol(woo, Decl(dependentReturnType1.ts, 313, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 316, 13)) ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>woo : Symbol(woo, Decl(dependentReturnType1.ts, 312, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 315, 13)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) x: T, ->x : Symbol(x, Decl(dependentReturnType1.ts, 316, 67)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 316, 13)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 315, 67)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 315, 13)) y: U, ->y : Symbol(y, Decl(dependentReturnType1.ts, 317, 9)) ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>y : Symbol(y, Decl(dependentReturnType1.ts, 316, 9)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) ): T extends string ->T : Symbol(T, Decl(dependentReturnType1.ts, 316, 13)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 315, 13)) ? U extends string ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) ? 1 : U extends number ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) ? 2 : never : T extends number ->T : Symbol(T, Decl(dependentReturnType1.ts, 316, 13)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 315, 13)) ? U extends number ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) ? 3 : U extends string ->U : Symbol(U, Decl(dependentReturnType1.ts, 316, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 315, 39)) ? 4 : never : never { if (typeof x === "number" && typeof y === "string") { ->x : Symbol(x, Decl(dependentReturnType1.ts, 316, 67)) ->y : Symbol(y, Decl(dependentReturnType1.ts, 317, 9)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 315, 67)) +>y : Symbol(y, Decl(dependentReturnType1.ts, 316, 9)) return 1; // Good error } @@ -920,46 +919,46 @@ function woo( } function ttt( ->ttt : Symbol(ttt, Decl(dependentReturnType1.ts, 336, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 338, 13)) ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>ttt : Symbol(ttt, Decl(dependentReturnType1.ts, 335, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 337, 13)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) x: T, ->x : Symbol(x, Decl(dependentReturnType1.ts, 338, 67)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 338, 13)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 337, 67)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 337, 13)) y: U, ->y : Symbol(y, Decl(dependentReturnType1.ts, 339, 9)) ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>y : Symbol(y, Decl(dependentReturnType1.ts, 338, 9)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) ): T extends string ->T : Symbol(T, Decl(dependentReturnType1.ts, 338, 13)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 337, 13)) ? U extends string ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) ? 1 : U extends number ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) ? 2 : never : T extends number ->T : Symbol(T, Decl(dependentReturnType1.ts, 338, 13)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 337, 13)) ? U extends number ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) ? 3 : U extends string ->U : Symbol(U, Decl(dependentReturnType1.ts, 338, 39)) +>U : Symbol(U, Decl(dependentReturnType1.ts, 337, 39)) ? 4 : never : never { if (typeof x === "number" && typeof y === "string") { ->x : Symbol(x, Decl(dependentReturnType1.ts, 338, 67)) ->y : Symbol(y, Decl(dependentReturnType1.ts, 339, 9)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 337, 67)) +>y : Symbol(y, Decl(dependentReturnType1.ts, 338, 9)) return 4; // Ok } @@ -970,22 +969,22 @@ function ttt( // Shadowing of the narrowed reference function shadowing(x: T): T extends 1 ? number : T extends 2 ? string : never { ->shadowing : Symbol(shadowing, Decl(dependentReturnType1.ts, 359, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 362, 19)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 362, 36)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 362, 19)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 362, 19)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 362, 19)) +>shadowing : Symbol(shadowing, Decl(dependentReturnType1.ts, 358, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 361, 19)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 361, 36)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 361, 19)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 361, 19)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 361, 19)) if (true) { let x: number = Math.random() ? 1 : 2; ->x : Symbol(x, Decl(dependentReturnType1.ts, 364, 11)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 363, 11)) >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.float16.d.ts, --, --)) >random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) if (x === 1) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 364, 11)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 363, 11)) return 1; // Error } @@ -994,16 +993,16 @@ function shadowing(x: T): T extends 1 ? number : T extends 2 ? } function noShadowing(x: T): T extends 1 ? number : T extends 2 ? string : never { ->noShadowing : Symbol(noShadowing, Decl(dependentReturnType1.ts, 370, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 372, 21)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 372, 38)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 372, 21)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 372, 21)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 372, 21)) +>noShadowing : Symbol(noShadowing, Decl(dependentReturnType1.ts, 369, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 371, 21)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 371, 38)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 371, 21)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 371, 21)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 371, 21)) if (true) { if (x === 1) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 372, 38)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 371, 38)) return 1; // Ok } @@ -1013,29 +1012,29 @@ function noShadowing(x: T): T extends 1 ? number : T extends 2 // If the narrowing reference is out of scope, we simply won't narrow its type declare let someX: boolean; ->someX : Symbol(someX, Decl(dependentReturnType1.ts, 382, 11)) +>someX : Symbol(someX, Decl(dependentReturnType1.ts, 381, 11)) function scope2(a: T): T extends true ? 1 : T extends false ? 2 : never { ->scope2 : Symbol(scope2, Decl(dependentReturnType1.ts, 382, 27)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 383, 16)) ->a : Symbol(a, Decl(dependentReturnType1.ts, 383, 35)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 383, 16)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 383, 16)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 383, 16)) +>scope2 : Symbol(scope2, Decl(dependentReturnType1.ts, 381, 27)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 382, 16)) +>a : Symbol(a, Decl(dependentReturnType1.ts, 382, 35)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 382, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 382, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 382, 16)) if ((true)) { const someX = a; ->someX : Symbol(someX, Decl(dependentReturnType1.ts, 385, 13)) ->a : Symbol(a, Decl(dependentReturnType1.ts, 383, 35)) +>someX : Symbol(someX, Decl(dependentReturnType1.ts, 384, 13)) +>a : Symbol(a, Decl(dependentReturnType1.ts, 382, 35)) if (someX) { // We narrow `someX` and the return type here ->someX : Symbol(someX, Decl(dependentReturnType1.ts, 385, 13)) +>someX : Symbol(someX, Decl(dependentReturnType1.ts, 384, 13)) return 1; } } if (!someX) { // This is a different `someX`, so we don't narrow here ->someX : Symbol(someX, Decl(dependentReturnType1.ts, 382, 11)) +>someX : Symbol(someX, Decl(dependentReturnType1.ts, 381, 11)) return 2; } @@ -1045,24 +1044,24 @@ function scope2(a: T): T extends true ? 1 : T extends false ? } function moreShadowing(x: T): T extends 1 ? number : T extends 2 ? string : never { ->moreShadowing : Symbol(moreShadowing, Decl(dependentReturnType1.ts, 395, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 397, 23)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 397, 40)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 397, 23)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 397, 23)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 397, 23)) +>moreShadowing : Symbol(moreShadowing, Decl(dependentReturnType1.ts, 394, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 396, 23)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 396, 40)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 396, 23)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 396, 23)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 396, 23)) if (x === 2) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 397, 40)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 396, 40)) let x: number = Math.random() ? 1 : 2; ->x : Symbol(x, Decl(dependentReturnType1.ts, 399, 11)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 398, 11)) >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.float16.d.ts, --, --)) >random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) if (x === 1) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 399, 11)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 398, 11)) return 1; // Error } @@ -1073,17 +1072,17 @@ function moreShadowing(x: T): T extends 1 ? number : T extends // This would be unsafe to narrow due to `infer` type. function withInfer(x: T): T extends [infer R] ? R : T extends number ? boolean : never { ->withInfer : Symbol(withInfer, Decl(dependentReturnType1.ts, 406, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 409, 19)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 409, 48)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 409, 19)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 409, 19)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 409, 71)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 409, 71)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 409, 19)) +>withInfer : Symbol(withInfer, Decl(dependentReturnType1.ts, 405, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 408, 19)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 408, 48)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 408, 19)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 408, 19)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 408, 71)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 408, 71)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 408, 19)) if (typeof x === "number") { ->x : Symbol(x, Decl(dependentReturnType1.ts, 409, 48)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 408, 48)) return true; } @@ -1091,22 +1090,22 @@ function withInfer(x: T): T extends [infer R] ? R : } const withInferResult = withInfer(["a"] as const); // The type says it returns `"a"`, but the function actually returns `""`. ->withInferResult : Symbol(withInferResult, Decl(dependentReturnType1.ts, 416, 5)) ->withInfer : Symbol(withInfer, Decl(dependentReturnType1.ts, 406, 1)) +>withInferResult : Symbol(withInferResult, Decl(dependentReturnType1.ts, 415, 5)) +>withInfer : Symbol(withInfer, Decl(dependentReturnType1.ts, 405, 1)) >const : Symbol(const) // Ok async function abool(x: T): Promise { ->abool : Symbol(abool, Decl(dependentReturnType1.ts, 416, 50)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 419, 21)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 419, 45)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 419, 21)) +>abool : Symbol(abool, Decl(dependentReturnType1.ts, 415, 50)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 418, 21)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 418, 45)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 418, 21)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 419, 21)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 419, 21)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 418, 21)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 418, 21)) if (x) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 419, 45)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 418, 45)) return 1; } @@ -1115,17 +1114,17 @@ async function abool(x: T): Promise(x: T): Generator { ->bbool : Symbol(bbool, Decl(dependentReturnType1.ts, 424, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 427, 16)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 427, 40)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 427, 16)) +>bbool : Symbol(bbool, Decl(dependentReturnType1.ts, 423, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 426, 16)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 426, 40)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 426, 16)) >Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 427, 16)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 427, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 426, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 426, 16)) yield 3; if (x) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 427, 40)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 426, 40)) return 1; } @@ -1134,16 +1133,16 @@ function* bbool(x: T): Generator(x: T): Generator { ->cbool : Symbol(cbool, Decl(dependentReturnType1.ts, 433, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 436, 16)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 436, 40)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 436, 16)) +>cbool : Symbol(cbool, Decl(dependentReturnType1.ts, 432, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 435, 16)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 435, 40)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 435, 16)) >Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 436, 16)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 436, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 435, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 435, 16)) if (x) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 436, 40)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 435, 40)) yield 1; } @@ -1153,121 +1152,121 @@ function* cbool(x: T): Generator { ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 445, 25)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 445, 27)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 444, 25)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 444, 27)) abstract perform(t: T): R; ->perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 446, 21)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 445, 25)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 445, 27)) +>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 445, 21)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 444, 25)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 444, 27)) } type ConditionalReturnType | undefined> = ->ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 447, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 449, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 449, 29)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 449, 32)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 449, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 449, 29)) +>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 446, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 448, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 448, 29)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 448, 32)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 448, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 448, 29)) EOp extends Operation ? R : EOp extends undefined ? T | R : never; ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 449, 32)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 449, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 449, 29)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 449, 29)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 449, 32)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 449, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 449, 29)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 448, 32)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 448, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 448, 29)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 448, 29)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 448, 32)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 448, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 448, 29)) class ConditionalOperation< ->ConditionalOperation : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 450, 76)) +>ConditionalOperation : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 449, 76)) T, ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) R, ->R : Symbol(R, Decl(dependentReturnType1.ts, 454, 6)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 453, 6)) EOp extends Operation | undefined, ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 455, 6)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 454, 6)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 454, 6)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 453, 6)) > extends Operation> { ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 447, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 454, 6)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 455, 6)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 446, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 453, 6)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 454, 6)) constructor( private predicate: (value: T) => boolean, ->predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 458, 16)) ->value : Symbol(value, Decl(dependentReturnType1.ts, 459, 28)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) +>predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 457, 16)) +>value : Symbol(value, Decl(dependentReturnType1.ts, 458, 28)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) private thenOp: Operation, ->thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 459, 49)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 454, 6)) +>thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 458, 49)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 453, 6)) private elseOp?: EOp, ->elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 460, 40)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 455, 6)) +>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 459, 40)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 454, 6)) ) { super(); ->super : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) +>super : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) } // We won't try to narrow the return type because `T` is declared on the class and we don't analyze this case. perform(t: T): ConditionalReturnType { ->perform : Symbol(ConditionalOperation.perform, Decl(dependentReturnType1.ts, 464, 5)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 467, 12)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 447, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 453, 27)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 454, 6)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 455, 6)) +>perform : Symbol(ConditionalOperation.perform, Decl(dependentReturnType1.ts, 463, 5)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 466, 12)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 446, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 452, 27)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 453, 6)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 454, 6)) if (this.predicate(t)) { ->this.predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 458, 16)) ->this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 450, 76)) ->predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 458, 16)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 467, 12)) +>this.predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 457, 16)) +>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 449, 76)) +>predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 457, 16)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 466, 12)) return this.thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it ->this.thenOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->this.thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 459, 49)) ->this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 450, 76)) ->thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 459, 49)) ->perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 467, 12)) +>this.thenOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>this.thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 458, 49)) +>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 449, 76)) +>thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 458, 49)) +>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 466, 12)) } else if (typeof this.elseOp !== "undefined") { ->this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 460, 40)) ->this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 450, 76)) ->elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 460, 40)) +>this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 459, 40)) +>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 449, 76)) +>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 459, 40)) return this.elseOp.perform(t); // Would be ok ->this.elseOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 460, 40)) ->this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 450, 76)) ->elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 460, 40)) ->perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 467, 12)) +>this.elseOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 459, 40)) +>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 449, 76)) +>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 459, 40)) +>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 466, 12)) } else { return t; // Would be ok ->t : Symbol(t, Decl(dependentReturnType1.ts, 467, 12)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 466, 12)) } } } @@ -1275,110 +1274,110 @@ class ConditionalOperation< // Like the version above, we will not attempt to narrow because there's more than one reference to `T`, // because `T` shows up in the type of `predicate`. function perform | undefined>( ->perform : Symbol(perform, Decl(dependentReturnType1.ts, 476, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 480, 19)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 480, 22)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 480, 19)) +>perform : Symbol(perform, Decl(dependentReturnType1.ts, 475, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 479, 19)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 479, 22)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 479, 19)) t: T, ->t : Symbol(t, Decl(dependentReturnType1.ts, 480, 64)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 479, 64)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) predicate: (value: T) => boolean, ->predicate : Symbol(predicate, Decl(dependentReturnType1.ts, 481, 9)) ->value : Symbol(value, Decl(dependentReturnType1.ts, 482, 16)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) +>predicate : Symbol(predicate, Decl(dependentReturnType1.ts, 480, 9)) +>value : Symbol(value, Decl(dependentReturnType1.ts, 481, 16)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) thenOp: Operation, ->thenOp : Symbol(thenOp, Decl(dependentReturnType1.ts, 482, 37)) ->Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 442, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 480, 19)) +>thenOp : Symbol(thenOp, Decl(dependentReturnType1.ts, 481, 37)) +>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 441, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 479, 19)) elseOp?: EOp, ->elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 483, 28)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 480, 22)) +>elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 482, 28)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 479, 22)) ): ConditionalReturnType { ->ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 447, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 480, 17)) ->R : Symbol(R, Decl(dependentReturnType1.ts, 480, 19)) ->EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 480, 22)) +>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 446, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 479, 17)) +>R : Symbol(R, Decl(dependentReturnType1.ts, 479, 19)) +>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 479, 22)) if (predicate(t)) { ->predicate : Symbol(predicate, Decl(dependentReturnType1.ts, 481, 9)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 480, 64)) +>predicate : Symbol(predicate, Decl(dependentReturnType1.ts, 480, 9)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 479, 64)) return thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it ->thenOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->thenOp : Symbol(thenOp, Decl(dependentReturnType1.ts, 482, 37)) ->perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 480, 64)) +>thenOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>thenOp : Symbol(thenOp, Decl(dependentReturnType1.ts, 481, 37)) +>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 479, 64)) } else if (elseOp !== undefined) { ->elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 483, 28)) +>elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 482, 28)) >undefined : Symbol(undefined) return elseOp.perform(t); // Would be ok ->elseOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 483, 28)) ->perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 445, 32)) ->t : Symbol(t, Decl(dependentReturnType1.ts, 480, 64)) +>elseOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>elseOp : Symbol(elseOp, Decl(dependentReturnType1.ts, 482, 28)) +>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 444, 32)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 479, 64)) } else { return t; // Would be ok ->t : Symbol(t, Decl(dependentReturnType1.ts, 480, 64)) +>t : Symbol(t, Decl(dependentReturnType1.ts, 479, 64)) } } // Return conditional expressions with parentheses function returnStuff1(x: T ): T extends true ? 1 : T extends false ? 2 : never { ->returnStuff1 : Symbol(returnStuff1, Decl(dependentReturnType1.ts, 493, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 496, 22)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 496, 41)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 496, 22)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 496, 22)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 496, 22)) +>returnStuff1 : Symbol(returnStuff1, Decl(dependentReturnType1.ts, 492, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 495, 22)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 495, 41)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 495, 22)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 495, 22)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 495, 22)) return (x ? (1) : 2); ->x : Symbol(x, Decl(dependentReturnType1.ts, 496, 41)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 495, 41)) } function returnStuff2(x: T ): ->returnStuff2 : Symbol(returnStuff2, Decl(dependentReturnType1.ts, 498, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 500, 22)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 500, 45)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 500, 22)) +>returnStuff2 : Symbol(returnStuff2, Decl(dependentReturnType1.ts, 497, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 499, 22)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 499, 45)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 499, 22)) T extends 1 ? "one" : T extends 2 ? "two" : T extends "a" ? 0 : never { ->T : Symbol(T, Decl(dependentReturnType1.ts, 500, 22)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 500, 22)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 500, 22)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 499, 22)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 499, 22)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 499, 22)) return (typeof x === "string" ? 0 : (x === 1 ? ("one") : "two")); ->x : Symbol(x, Decl(dependentReturnType1.ts, 500, 45)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 500, 45)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 499, 45)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 499, 45)) } // If the conditional type's input is `never`, then it resolves to `never`: function neverOk(x: T): T extends true ? 1 : T extends false ? 2 : never { ->neverOk : Symbol(neverOk, Decl(dependentReturnType1.ts, 503, 1)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 506, 17)) ->x : Symbol(x, Decl(dependentReturnType1.ts, 506, 36)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 506, 17)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 506, 17)) ->T : Symbol(T, Decl(dependentReturnType1.ts, 506, 17)) +>neverOk : Symbol(neverOk, Decl(dependentReturnType1.ts, 502, 1)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 505, 17)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 505, 36)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 505, 17)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 505, 17)) +>T : Symbol(T, Decl(dependentReturnType1.ts, 505, 17)) if (x === true) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 506, 36)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 505, 36)) return 1; } if (x === false) { ->x : Symbol(x, Decl(dependentReturnType1.ts, 506, 36)) +>x : Symbol(x, Decl(dependentReturnType1.ts, 505, 36)) return 2; } diff --git a/tests/baselines/reference/dependentReturnType1.types b/tests/baselines/reference/dependentReturnType1.types index 96265db6b57be..6cf093f710f2e 100644 --- a/tests/baselines/reference/dependentReturnType1.types +++ b/tests/baselines/reference/dependentReturnType1.types @@ -1246,7 +1246,6 @@ function badCapitalize( } } -// No narrowing because conditional's extends type is different from type parameter constraint types function voidRet( >voidRet : (x: T) => T extends {} ? void : T extends undefined ? number : never > : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ diff --git a/tests/cases/compiler/dependentReturnType1.ts b/tests/cases/compiler/dependentReturnType1.ts index 7527d3015bc3b..8633615892771 100644 --- a/tests/cases/compiler/dependentReturnType1.ts +++ b/tests/cases/compiler/dependentReturnType1.ts @@ -307,7 +307,6 @@ function badCapitalize( } } -// No narrowing because conditional's extends type is different from type parameter constraint types function voidRet( x: T ): T extends {} ? void : T extends undefined ? number : never {