-
Notifications
You must be signed in to change notification settings - Fork 12.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
13cf64e
commit a0fbf5c
Showing
5 changed files
with
926 additions
and
0 deletions.
There are no files selected for viewing
114 changes: 114 additions & 0 deletions
114
tests/baselines/reference/controlFlowGenericTypes.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(49,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. | ||
Property 'foo' does not exist on type 'AA'. | ||
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(58,44): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. | ||
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(59,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. | ||
Property 'foo' does not exist on type 'AA'. | ||
|
||
|
||
==== tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts (3 errors) ==== | ||
function f1<T extends string | undefined>(x: T, y: { a: T }, z: [T]): string { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
if (y.a) { | ||
y.a.length; | ||
return y.a; | ||
} | ||
if (z[0]) { | ||
z[0].length; | ||
return z[0]; | ||
} | ||
return "hello"; | ||
} | ||
|
||
function f2<T>(x: Extract<T, string | undefined> | null): string { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
return "hello"; | ||
} | ||
|
||
// Repro from #13995 | ||
|
||
declare function takeA(val: 'A'): void; | ||
export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB { | ||
if (value === 'A') { | ||
takeA(value); | ||
return value; | ||
} | ||
else { | ||
return value; | ||
} | ||
} | ||
|
||
// Repro from #13995 | ||
|
||
type Common = { id: number }; | ||
type AA = { tag: 'A', id: number }; | ||
type BB = { tag: 'B', id: number, foo: number }; | ||
|
||
type MyUnion = AA | BB; | ||
|
||
const fn = (value: MyUnion) => { | ||
value.foo; // Error | ||
~~~ | ||
!!! error TS2339: Property 'foo' does not exist on type 'MyUnion'. | ||
!!! error TS2339: Property 'foo' does not exist on type 'AA'. | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
|
||
const fn2 = <T extends MyUnion>(value: T): MyUnion => { | ||
~~~~~~~ | ||
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. | ||
value.foo; // Error | ||
~~~ | ||
!!! error TS2339: Property 'foo' does not exist on type 'MyUnion'. | ||
!!! error TS2339: Property 'foo' does not exist on type 'AA'. | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
|
||
// Repro from #13995 | ||
|
||
type A1 = { | ||
testable: true | ||
doTest: () => void | ||
} | ||
type B1 = { | ||
testable: false | ||
}; | ||
|
||
type Union = A1 | B1 | ||
|
||
function notWorking<T extends Union>(object: T) { | ||
if (!object.testable) return; | ||
object.doTest(); | ||
} | ||
|
||
// Repro from #42939 | ||
|
||
interface A { | ||
a: number | null; | ||
}; | ||
|
||
function get<K extends keyof A>(key: K, obj: A): number { | ||
const value = obj[key]; | ||
if (value !== null) { | ||
return value; | ||
} | ||
return 0; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
//// [controlFlowGenericTypes.ts] | ||
function f1<T extends string | undefined>(x: T, y: { a: T }, z: [T]): string { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
if (y.a) { | ||
y.a.length; | ||
return y.a; | ||
} | ||
if (z[0]) { | ||
z[0].length; | ||
return z[0]; | ||
} | ||
return "hello"; | ||
} | ||
|
||
function f2<T>(x: Extract<T, string | undefined> | null): string { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
return "hello"; | ||
} | ||
|
||
// Repro from #13995 | ||
|
||
declare function takeA(val: 'A'): void; | ||
export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB { | ||
if (value === 'A') { | ||
takeA(value); | ||
return value; | ||
} | ||
else { | ||
return value; | ||
} | ||
} | ||
|
||
// Repro from #13995 | ||
|
||
type Common = { id: number }; | ||
type AA = { tag: 'A', id: number }; | ||
type BB = { tag: 'B', id: number, foo: number }; | ||
|
||
type MyUnion = AA | BB; | ||
|
||
const fn = (value: MyUnion) => { | ||
value.foo; // Error | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
|
||
const fn2 = <T extends MyUnion>(value: T): MyUnion => { | ||
value.foo; // Error | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
|
||
// Repro from #13995 | ||
|
||
type A1 = { | ||
testable: true | ||
doTest: () => void | ||
} | ||
type B1 = { | ||
testable: false | ||
}; | ||
|
||
type Union = A1 | B1 | ||
|
||
function notWorking<T extends Union>(object: T) { | ||
if (!object.testable) return; | ||
object.doTest(); | ||
} | ||
|
||
// Repro from #42939 | ||
|
||
interface A { | ||
a: number | null; | ||
}; | ||
|
||
function get<K extends keyof A>(key: K, obj: A): number { | ||
const value = obj[key]; | ||
if (value !== null) { | ||
return value; | ||
} | ||
return 0; | ||
}; | ||
|
||
|
||
//// [controlFlowGenericTypes.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.bounceAndTakeIfA = void 0; | ||
function f1(x, y, z) { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
if (y.a) { | ||
y.a.length; | ||
return y.a; | ||
} | ||
if (z[0]) { | ||
z[0].length; | ||
return z[0]; | ||
} | ||
return "hello"; | ||
} | ||
function f2(x) { | ||
if (x) { | ||
x; | ||
x.length; | ||
return x; | ||
} | ||
return "hello"; | ||
} | ||
function bounceAndTakeIfA(value) { | ||
if (value === 'A') { | ||
takeA(value); | ||
return value; | ||
} | ||
else { | ||
return value; | ||
} | ||
} | ||
exports.bounceAndTakeIfA = bounceAndTakeIfA; | ||
var fn = function (value) { | ||
value.foo; // Error | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
var fn2 = function (value) { | ||
value.foo; // Error | ||
if ('foo' in value) { | ||
value.foo; | ||
} | ||
if (value.tag === 'B') { | ||
value.foo; | ||
} | ||
}; | ||
function notWorking(object) { | ||
if (!object.testable) | ||
return; | ||
object.doTest(); | ||
} | ||
; | ||
function get(key, obj) { | ||
var value = obj[key]; | ||
if (value !== null) { | ||
return value; | ||
} | ||
return 0; | ||
} | ||
; |
Oops, something went wrong.