tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(49,15): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'Box<T>'.
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(55,15): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'Box<unknown>'.
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(81,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(90,44): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(91,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 (5 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";
    }
    
    interface Box<T> {
        item: T;
    }
    
    declare function isBox(x: any): x is Box<unknown>;
    declare function isUndefined(x: unknown): x is undefined;
    declare function unbox<T>(x: Box<T>): T;
    
    function g1<T extends Box<T> | undefined>(x: T) {
        if (isBox(x)) {
            unbox(x);
        }
    }
    
    function g2<T extends Box<T> | undefined>(x: T) {
        if (!isUndefined(x)) {
            unbox(x);
        }
    }
    
    function g3<T extends Box<T> | undefined>(x: T) {
        if (!isBox(x)) {
            unbox(x);  // Error
                  ~
!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'Box<T>'.
        }
    }
    
    function g4<T extends Box<T> | undefined>(x: T) {
        if (isUndefined(x)) {
            unbox(x);  // Error
                  ~
!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'Box<unknown>'.
        }
    }
    
    // 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;
    };
    