// @strict: true // @declaration: true type T01 = {} & string; // {} & string type T02 = {} & 'a'; // 'a' type T03 = {} & object; // object type T04 = {} & { x: number }; // { x: number } type T05 = {} & null; // never type T06 = {} & undefined; // never type T07 = undefined & void; // undefined type T10 = string & {}; // Specially preserved type T11 = number & {}; // Specially preserved type T12 = bigint & {}; // Specially preserved type ThisNode = {}; type ThatNode = {}; type ThisOrThatNode = ThisNode | ThatNode; function f01(u: unknown) { let x1: {} = u; // Error let x2: {} | null | undefined = u; let x3: {} | { x: string } | null | undefined = u; let x4: ThisOrThatNode | null | undefined = u; } function f10(x: unknown) { if (x) { x; // {} } else { x; // unknown } if (!x) { x; // unknown } else { x; // {} } } function f11(x: T) { if (x) { x; // T & {} } else { x; // T } if (!x) { x; // T } else { x; // T & {} } } function f12(x: T) { if (x) { x; // T } else { x; // T } } function f20(x: unknown) { if (x !== undefined) { x; // {} | null } else { x; // undefined } if (x !== null) { x; // {} | undefined } else { x; // null } if (x !== undefined && x !== null) { x; // {} } else { x; // null | undefined } if (x != undefined) { x; // {} } else { x; // null | undefined } if (x != null) { x; // {} } else { x; // null | undefined } } function f21(x: T) { if (x !== undefined) { x; // T & ({} | null) } else { x; // T } if (x !== null) { x; // T & ({} | undefined) } else { x; // T } if (x !== undefined && x !== null) { x; // T & {} } else { x; // T } if (x != undefined) { x; // T & {} } else { x; // T } if (x != null) { x; // T & {} } else { x; // T } } function f22(x: T) { if (x !== undefined) { x; // T & {} } else { x; // T } if (x !== null) { x; // T } else { x; // T } if (x !== undefined && x !== null) { x; // T & {} } else { x; // T } if (x != undefined) { x; // T & {} } else { x; // T } if (x != null) { x; // T & {} } else { x; // T } } function f23(x: T | undefined | null) { if (x !== undefined) { x; // T & {} | null } if (x !== null) { x; // T & {} | undefined } if (x != undefined) { x; // T & {} } if (x != null) { x; // T & {} } } function f30(x: {}) { if (typeof x === "object") { x; // object } } function f31(x: T) { if (typeof x === "object") { x; // T & object | T & null } if (x && typeof x === "object") { x; // T & object } if (typeof x === "object" && x) { x; // T & object } } function f32(x: T) { if (typeof x === "object") { x; // T & object } } function possiblyNull(x: T) { return !!true ? x : null; // T | null } function possiblyUndefined(x: T) { return !!true ? x : undefined; // T | undefined } function possiblyNullOrUndefined(x: T) { return possiblyUndefined(possiblyNull(x)); // T | null | undefined } function ensureNotNull(x: T) { if (x === null) throw Error(); return x; // T & ({} | undefined) } function ensureNotUndefined(x: T) { if (x === undefined) throw Error(); return x; // T & ({} | null) } function ensureNotNullOrUndefined(x: T) { return ensureNotUndefined(ensureNotNull(x)); // T & {} } function f40(a: string | undefined, b: number | null | undefined) { let a1 = ensureNotNullOrUndefined(a); // string let b1 = ensureNotNullOrUndefined(b); // number } type QQ = NonNullable>>; function f41(a: T) { let a1 = ensureNotUndefined(ensureNotNull(a)); // T & {} let a2 = ensureNotNull(ensureNotUndefined(a)); // T & {} let a3 = ensureNotNull(ensureNotNull(a)); // T & {} | T & undefined let a4 = ensureNotUndefined(ensureNotUndefined(a)); // T & {} | T & null let a5 = ensureNotNullOrUndefined(ensureNotNullOrUndefined(a)); // T & {} let a6 = ensureNotNull(possiblyNullOrUndefined(a)); // T & {} | undefined let a7 = ensureNotUndefined(possiblyNullOrUndefined(a)); // T & {} | null let a8 = ensureNotNull(possiblyUndefined(a)); // T & {} | undefined let a9 = ensureNotUndefined(possiblyNull(a)); // T & {} | null } // Repro from #48468 function deepEquals(a: T, b: T): boolean { if (typeof a !== 'object' || typeof b !== 'object' || !a || !b) { return false; } if (Array.isArray(a) || Array.isArray(b)) { return false; } if (Object.keys(a).length !== Object.keys(b).length) { // Error here return false; } return true; } // Repro from #49386 function foo(x: T | null) { let y = x; if (y !== null) { y; } } // We allow an unconstrained object of a generic type `T` to be indexed by a key of type `keyof T` // without a check that the object is non-undefined and non-null. This is safe because `keyof T` // is `never` (meaning no possible keys) for any `T` that includes `undefined` or `null`. function ff1(t: T, k: keyof T) { t[k]; } function ff2(t: T & {}, k: keyof T) { t[k]; } function ff3(t: T, k: keyof (T & {})) { t[k]; // Error } function ff4(t: T & {}, k: keyof (T & {})) { t[k]; } ff1(null, 'foo'); // Error ff2(null, 'foo'); // Error ff3(null, 'foo'); ff4(null, 'foo'); // Error // Repro from #49681 type Foo = { [key: string]: unknown }; type NullableFoo = Foo | undefined; type Bar = NonNullable[string]; // Generics and intersections with {} function fx0(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } function fx1(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } function fx2(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } function fx3(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } function fx4(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } function fx5(value: T & ({} | null)) { if (value === 42) { value; // T & {} } else { value; // T & ({} | null) } } // Double-equals narrowing function fx10(x: string | number, y: number) { if (x == y) { x; // string | number } else { x; // string | number } if (x != y) { x; // string | number } else { x; // string | number } } // Repros from #50706 function SendBlob(encoding: unknown) { if (encoding !== undefined && encoding !== 'utf8') { throw new Error('encoding'); } encoding; }; function doSomething1(value: T): T { if (value === undefined) { return value; } if (value === 42) { throw Error('Meaning of life value'); } return value; } function doSomething2(value: unknown): void { if (value === undefined) { return; } if (value === 42) { value; } } // Repro from #51009 type TypeA = { A: 'A', B: 'B', } type TypeB = { A: 'A', B: 'B', C: 'C', } type R = T extends keyof TypeB ? [TypeA[T], TypeB[T]] : never; type R2 = T extends keyof TypeA ? T extends keyof TypeB ? [TypeA[T], TypeB[T]] : never : never; // Repro from #51041 type AB = "A" | "B"; function x(x: T_AB & undefined, y: any) { let r2: never = y as T_AB & undefined; } // Repro from #51538 type Left = 'left'; type Right = 'right' & { right: 'right' }; type Either = Left | Right; function assertNever(v: never): never { throw new Error('never'); } function fx20(value: Either) { if (value === 'left') { const foo: 'left' = value; } else if (value === 'right') { const bar: 'right' = value; } else { assertNever(value); } }