diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f05c9b40df23..342c3f22e3031 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1226,8 +1226,11 @@ export const enum TypeFacts { Falsy = 1 << 23, // !x IsUndefined = 1 << 24, // Contains undefined or intersection with undefined IsNull = 1 << 25, // Contains null or intersection with null + IsPossiblyUndefined = 1 << 26, // Possibly undefined + IsPossiblyNull = 1 << 27, // Possibly null IsUndefinedOrNull = IsUndefined | IsNull, - All = (1 << 27) - 1, + IsPossiblyUndefinedOrNull = IsPossiblyUndefined | IsPossiblyNull, + All = (1 << 29) - 1, // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. @@ -1270,11 +1273,12 @@ export const enum TypeFacts { FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, - UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined, - NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull, - EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull), - EmptyObjectFacts = All & ~IsUndefinedOrNull, - UnknownFacts = All & ~IsUndefinedOrNull, + UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined | IsPossiblyUndefined, + NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull | IsPossiblyNull, + EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull | IsPossiblyUndefinedOrNull), + EmptyObjectFacts = All & ~(IsUndefinedOrNull | IsPossiblyUndefinedOrNull), + UnknownStrictFacts = All & ~IsUndefinedOrNull, + UnknownFacts = All & ~(IsUndefinedOrNull | IsPossiblyUndefinedOrNull), AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined, // Masks OrFactsMask = TypeofEQFunction | TypeofNEObject, @@ -27477,7 +27481,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & TypeFlags.Intersection) { return getIntersectionTypeFacts(type as IntersectionType, callerOnlyNeeds); } - return TypeFacts.UnknownFacts; + return strictNullChecks && flags & TypeFlags.Unknown ? TypeFacts.UnknownStrictFacts : TypeFacts.UnknownFacts; } function getIntersectionTypeFacts(type: IntersectionType, callerOnlyNeeds: TypeFacts): TypeFacts { @@ -29665,15 +29669,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isConstraintPosition(type: Type, node: Node) { const parent = node.parent; - // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of - // a generic type without a nullable constraint and x is a generic type. This is because when both obj - // and x are of generic types T and K, we want the resulting type to be T[K]. + // In an element access obj[key], we consider obj to be in a constraint position, except when + // obj and key both have generic types. When obj and key are of generic types T and K, we want + // the resulting type to be T[K]. return parent.kind === SyntaxKind.PropertyAccessExpression || parent.kind === SyntaxKind.QualifiedName || parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node || parent.kind === SyntaxKind.NewExpression && (parent as NewExpression).expression === node || parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node && - !(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression))); + !(isGenericObjectType(type) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression))); } function isGenericTypeWithUnionConstraint(type: Type): boolean { @@ -29682,12 +29686,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union)); } - function isGenericTypeWithoutNullableConstraint(type: Type): boolean { - return type.flags & TypeFlags.Intersection ? - some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) : - !!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable)); - } - function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) { // Computing the contextual type for a child of a JSX element involves resolving the type of the // element's tag name, so we exclude that here to avoid circularities. @@ -33705,7 +33703,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics._0_is_possibly_null_or_undefined : Diagnostics._0_is_possibly_undefined : Diagnostics._0_is_possibly_null, @@ -33715,7 +33713,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics.Object_is_possibly_null_or_undefined : Diagnostics.Object_is_possibly_undefined : Diagnostics.Object_is_possibly_null, @@ -33726,7 +33724,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined : Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined : Diagnostics.Cannot_invoke_an_object_which_is_possibly_null, @@ -33749,8 +33747,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(node, Diagnostics.Object_is_of_type_unknown); return errorType; } - const facts = getTypeFacts(type, TypeFacts.IsUndefinedOrNull); - if (facts & TypeFacts.IsUndefinedOrNull) { + const facts = getTypeFacts(type, TypeFacts.IsPossiblyUndefinedOrNull); + if (facts & TypeFacts.IsPossiblyUndefinedOrNull) { reportError(node, facts); const t = getNonNullableType(type); return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t; @@ -34589,14 +34587,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkIndexedAccess(node: ElementAccessExpression, checkMode: CheckMode | undefined): Type { - return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) : - checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode); - } - - function checkElementAccessChain(node: ElementAccessChain, checkMode: CheckMode | undefined) { + const isOptional = node.flags & NodeFlags.OptionalChain; const exprType = checkExpression(node.expression); - const nonOptionalType = getOptionalExpressionType(exprType, node.expression); - return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), node, nonOptionalType !== exprType); + const nonOptionalType = isOptional ? getOptionalExpressionType(exprType, node.expression) : exprType; + const nonNullType = maybeTypeOfKind(nonOptionalType, TypeFlags.Unknown | TypeFlags.Nullable) ? checkNonNullType(nonOptionalType, node.expression) : nonOptionalType; + const elementType = checkElementAccessExpression(node, nonNullType, checkMode); + return isOptional ? propagateOptionalTypeMarker(elementType, node as ElementAccessChain, nonOptionalType !== exprType) : elementType; } function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type, checkMode: CheckMode | undefined): Type { diff --git a/tests/baselines/reference/controlFlowGenericTypes.errors.txt b/tests/baselines/reference/controlFlowGenericTypes.errors.txt index 27101aaa81cc4..f78e67823d8f7 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.errors.txt +++ b/tests/baselines/reference/controlFlowGenericTypes.errors.txt @@ -5,9 +5,9 @@ controlFlowGenericTypes.ts(81,11): error TS2339: Property 'foo' does not exist o controlFlowGenericTypes.ts(90,44): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. controlFlowGenericTypes.ts(91,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. Property 'foo' does not exist on type 'AA'. -controlFlowGenericTypes.ts(156,16): error TS18048: 'obj' is possibly 'undefined'. -controlFlowGenericTypes.ts(167,9): error TS18048: 'iSpec' is possibly 'undefined'. -controlFlowGenericTypes.ts(168,9): error TS18048: 'iSpec' is possibly 'undefined'. +controlFlowGenericTypes.ts(176,16): error TS18049: 'obj' is possibly 'null' or 'undefined'. +controlFlowGenericTypes.ts(182,16): error TS18049: 'obj' is possibly 'null' or 'undefined'. +controlFlowGenericTypes.ts(195,9): error TS2536: Type 'keyof PublicSpec' cannot be used to index type 'InternalSpec'. ==== controlFlowGenericTypes.ts (8 errors) ==== @@ -163,25 +163,54 @@ controlFlowGenericTypes.ts(168,9): error TS18048: 'iSpec' is possibly 'undefined emittingObject.off(eventName as typeof eventName, 0); } - // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of - // a generic type without a nullable constraint and x is a generic type. This is because when both obj - // and x are of generic types T and K, we want the resulting type to be T[K]. + // In an element access obj[key], we consider obj to be in a constraint position, except when + // obj and key both have generic types. When obj and key are of generic types T and K, we want + // the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx6(obj: T | null | undefined, key: K) { const x1 = obj[key]; // Error ~~~ -!!! error TS18048: 'obj' is possibly 'undefined'. +!!! error TS18049: 'obj' is possibly 'null' or 'undefined'. const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + ~~~ +!!! error TS18049: 'obj' is possibly 'null' or 'undefined'. + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166 @@ -191,12 +220,10 @@ controlFlowGenericTypes.ts(168,9): error TS18048: 'iSpec' is possibly 'undefined InternalSpec extends Record | undefined = undefined> { m() { let iSpec = null! as InternalSpec; - iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined - ~~~~~ -!!! error TS18048: 'iSpec' is possibly 'undefined'. - iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined - ~~~~~ -!!! error TS18048: 'iSpec' is possibly 'undefined'. + iSpec[null! as keyof InternalSpec]; + iSpec[null! as keyof PublicSpec]; // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2536: Type 'keyof PublicSpec' cannot be used to index type 'InternalSpec'. if (iSpec === undefined) { return; } diff --git a/tests/baselines/reference/controlFlowGenericTypes.js b/tests/baselines/reference/controlFlowGenericTypes.js index d22dd7421ed0c..4236bf88bf9d7 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.js +++ b/tests/baselines/reference/controlFlowGenericTypes.js @@ -141,23 +141,50 @@ function once>(emittingObject: T, eventName: keyo emittingObject.off(eventName as typeof eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx6(obj: T | null | undefined, key: K) { const x1 = obj[key]; // Error const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166 @@ -167,8 +194,8 @@ class TableBaseEnum< InternalSpec extends Record | undefined = undefined> { m() { let iSpec = null! as InternalSpec; - iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined - iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined + iSpec[null! as keyof InternalSpec]; + iSpec[null! as keyof PublicSpec]; // Error if (iSpec === undefined) { return; } @@ -327,20 +354,43 @@ function once(emittingObject, eventName) { emittingObject.off(eventName, 0); emittingObject.off(eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj, key) { var x1 = obj[key]; var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; } function fx2(obj, key) { var x1 = obj[key]; var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; } function fx3(obj, key) { + var x1 = obj[key]; + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx4(obj, key) { + var x1 = obj[key]; + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx5(obj, key) { + var x1 = obj[key]; + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx6(obj, key) { var x1 = obj[key]; // Error var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx7(obj, key) { + var x1 = obj.x[key]; // Error + var x2 = obj && obj.x[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj.x[key]; } // Repro from #44166 var TableBaseEnum = /** @class */ (function () { @@ -348,8 +398,8 @@ var TableBaseEnum = /** @class */ (function () { } TableBaseEnum.prototype.m = function () { var iSpec = null; - iSpec[null]; // Error, object possibly undefined - iSpec[null]; // Error, object possibly undefined + iSpec[null]; + iSpec[null]; // Error if (iSpec === undefined) { return; } diff --git a/tests/baselines/reference/controlFlowGenericTypes.symbols b/tests/baselines/reference/controlFlowGenericTypes.symbols index a96581cb4ab9b..136b21aef62f6 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.symbols +++ b/tests/baselines/reference/controlFlowGenericTypes.symbols @@ -407,9 +407,9 @@ function once>(emittingObject: T, eventName: keyo >eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64)) } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { >fx1 : Symbol(fx1, Decl(controlFlowGenericTypes.ts, 138, 1)) @@ -430,227 +430,357 @@ function fx1(obj: T, key: K) { >x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 146, 9)) >obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) >obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 144, 42)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 147, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) >key : Symbol(key, Decl(controlFlowGenericTypes.ts, 144, 42)) } function fx2, K extends keyof T>(obj: T, key: K) { ->fx2 : Symbol(fx2, Decl(controlFlowGenericTypes.ts, 147, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) +>fx2 : Symbol(fx2, Decl(controlFlowGenericTypes.ts, 148, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 149, 47)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 149, 47)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 150, 47)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 150, 47)) const x1 = obj[key]; ->x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 150, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 151, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) const x2 = obj && obj[key]; ->x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 151, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 152, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 153, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { ->fx3 : Symbol(fx3, Decl(controlFlowGenericTypes.ts, 152, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) +>fx3 : Symbol(fx3, Decl(controlFlowGenericTypes.ts, 154, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 154, 59)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 154, 59)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 156, 59)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 156, 59)) + + const x1 = obj[key]; +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 157, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 158, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 159, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) +} + +function fx4(obj: T, key: K) { +>fx4 : Symbol(fx4, Decl(controlFlowGenericTypes.ts, 160, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 162, 31)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 162, 31)) + + const x1 = obj[key]; +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 163, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 164, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 165, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) +} + +function fx5(obj: T, key: K) { +>fx5 : Symbol(fx5, Decl(controlFlowGenericTypes.ts, 166, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 168, 45)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 168, 45)) + + const x1 = obj[key]; +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 169, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 170, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 171, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) +} + +function fx6(obj: T | null | undefined, key: K) { +>fx6 : Symbol(fx6, Decl(controlFlowGenericTypes.ts, 172, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 174, 15)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 174, 15)) const x1 = obj[key]; // Error ->x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 155, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 175, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) const x2 = obj && obj[key]; ->x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 156, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 176, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 177, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) +} + +function fx7(obj: { x: T } | null | undefined, key: K) { +>fx7 : Symbol(fx7, Decl(controlFlowGenericTypes.ts, 178, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 180, 15)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 180, 15)) + + const x1 = obj.x[key]; // Error +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 181, 9)) +>obj.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) + + const x2 = obj && obj.x[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 182, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>obj.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) + + const x3 = obj?.x[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 183, 9)) +>obj?.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) } // Repro from #44166 class TableBaseEnum< ->TableBaseEnum : Symbol(TableBaseEnum, Decl(controlFlowGenericTypes.ts, 157, 1)) +>TableBaseEnum : Symbol(TableBaseEnum, Decl(controlFlowGenericTypes.ts, 184, 1)) PublicSpec extends Record, ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) InternalSpec extends Record | undefined = undefined> { ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) m() { ->m : Symbol(TableBaseEnum.m, Decl(controlFlowGenericTypes.ts, 163, 82)) +>m : Symbol(TableBaseEnum.m, Decl(controlFlowGenericTypes.ts, 190, 82)) let iSpec = null! as InternalSpec; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) - iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) + iSpec[null! as keyof InternalSpec]; +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) - iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) + iSpec[null! as keyof PublicSpec]; // Error +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) if (iSpec === undefined) { ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) >undefined : Symbol(undefined) return; } iSpec[null! as keyof InternalSpec]; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) iSpec[null! as keyof PublicSpec]; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) } } // Repros from #45145 function f10(x: T, y: Partial) { ->f10 : Symbol(f10, Decl(controlFlowGenericTypes.ts, 174, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) ->a : Symbol(a, Decl(controlFlowGenericTypes.ts, 178, 24)) ->x : Symbol(x, Decl(controlFlowGenericTypes.ts, 178, 50)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) ->y : Symbol(y, Decl(controlFlowGenericTypes.ts, 178, 55)) +>f10 : Symbol(f10, Decl(controlFlowGenericTypes.ts, 201, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) +>a : Symbol(a, Decl(controlFlowGenericTypes.ts, 205, 24)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 205, 50)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) +>y : Symbol(y, Decl(controlFlowGenericTypes.ts, 205, 55)) >Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) y = x; ->y : Symbol(y, Decl(controlFlowGenericTypes.ts, 178, 55)) ->x : Symbol(x, Decl(controlFlowGenericTypes.ts, 178, 50)) +>y : Symbol(y, Decl(controlFlowGenericTypes.ts, 205, 55)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 205, 50)) } type SqlInsertSet = T extends undefined ? object : { [P in keyof T]: unknown }; ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) ->P : Symbol(P, Decl(controlFlowGenericTypes.ts, 182, 57)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) +>P : Symbol(P, Decl(controlFlowGenericTypes.ts, 209, 57)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) class SqlTable { ->SqlTable : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 182, 82)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>SqlTable : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 209, 82)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) protected validateRow(_row: Partial>): void { ->validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->_row : Symbol(_row, Decl(controlFlowGenericTypes.ts, 185, 26)) +>validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>_row : Symbol(_row, Decl(controlFlowGenericTypes.ts, 212, 26)) >Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) } public insertRow(row: SqlInsertSet) { ->insertRow : Symbol(SqlTable.insertRow, Decl(controlFlowGenericTypes.ts, 186, 5)) ->row : Symbol(row, Decl(controlFlowGenericTypes.ts, 187, 21)) ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>insertRow : Symbol(SqlTable.insertRow, Decl(controlFlowGenericTypes.ts, 213, 5)) +>row : Symbol(row, Decl(controlFlowGenericTypes.ts, 214, 21)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) this.validateRow(row); ->this.validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->this : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 182, 82)) ->validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->row : Symbol(row, Decl(controlFlowGenericTypes.ts, 187, 21)) +>this.validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>this : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 209, 82)) +>validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>row : Symbol(row, Decl(controlFlowGenericTypes.ts, 214, 21)) } } // Repro from #46495 interface Button { ->Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 190, 1)) +>Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 217, 1)) type: "button"; ->type : Symbol(Button.type, Decl(controlFlowGenericTypes.ts, 194, 18)) +>type : Symbol(Button.type, Decl(controlFlowGenericTypes.ts, 221, 18)) text: string; ->text : Symbol(Button.text, Decl(controlFlowGenericTypes.ts, 195, 19)) +>text : Symbol(Button.text, Decl(controlFlowGenericTypes.ts, 222, 19)) } interface Checkbox { ->Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 197, 1)) +>Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 224, 1)) type: "checkbox"; ->type : Symbol(Checkbox.type, Decl(controlFlowGenericTypes.ts, 199, 20)) +>type : Symbol(Checkbox.type, Decl(controlFlowGenericTypes.ts, 226, 20)) isChecked: boolean; ->isChecked : Symbol(Checkbox.isChecked, Decl(controlFlowGenericTypes.ts, 200, 21)) +>isChecked : Symbol(Checkbox.isChecked, Decl(controlFlowGenericTypes.ts, 227, 21)) } type Control = Button | Checkbox; ->Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 202, 1)) ->Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 190, 1)) ->Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 197, 1)) +>Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 229, 1)) +>Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 217, 1)) +>Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 224, 1)) function update(control : T | undefined, key: K, value: T[K]): void { ->update : Symbol(update, Decl(controlFlowGenericTypes.ts, 204, 33)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 202, 1)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 206, 78)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) ->value : Symbol(value, Decl(controlFlowGenericTypes.ts, 206, 86)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) +>update : Symbol(update, Decl(controlFlowGenericTypes.ts, 231, 33)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 229, 1)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 233, 78)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) +>value : Symbol(value, Decl(controlFlowGenericTypes.ts, 233, 86)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) if (control !== undefined) { ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) >undefined : Symbol(undefined) control[key] = value; ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 206, 78)) ->value : Symbol(value, Decl(controlFlowGenericTypes.ts, 206, 86)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 233, 78)) +>value : Symbol(value, Decl(controlFlowGenericTypes.ts, 233, 86)) } } // Repro from #50465 type Column = (keyof T extends never ? { id?: number | string } : { id: T }) & { title?: string; } ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->id : Symbol(id, Decl(controlFlowGenericTypes.ts, 214, 43)) ->id : Symbol(id, Decl(controlFlowGenericTypes.ts, 214, 70)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->title : Symbol(title, Decl(controlFlowGenericTypes.ts, 214, 83)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>id : Symbol(id, Decl(controlFlowGenericTypes.ts, 241, 43)) +>id : Symbol(id, Decl(controlFlowGenericTypes.ts, 241, 70)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>title : Symbol(title, Decl(controlFlowGenericTypes.ts, 241, 83)) function getColumnProperty(column: Column, key: keyof Column) { ->getColumnProperty : Symbol(getColumnProperty, Decl(controlFlowGenericTypes.ts, 214, 101)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) ->column : Symbol(column, Decl(controlFlowGenericTypes.ts, 216, 30)) ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 216, 48)) ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) +>getColumnProperty : Symbol(getColumnProperty, Decl(controlFlowGenericTypes.ts, 241, 101)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) +>column : Symbol(column, Decl(controlFlowGenericTypes.ts, 243, 30)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 243, 48)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) return column[key]; ->column : Symbol(column, Decl(controlFlowGenericTypes.ts, 216, 30)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 216, 48)) +>column : Symbol(column, Decl(controlFlowGenericTypes.ts, 243, 30)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 243, 48)) } diff --git a/tests/baselines/reference/controlFlowGenericTypes.types b/tests/baselines/reference/controlFlowGenericTypes.types index 34aaf80709138..2eaff9186c40c 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.types +++ b/tests/baselines/reference/controlFlowGenericTypes.types @@ -583,9 +583,9 @@ function once>(emittingObject: T, eventName: keyo > : ^ } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { >fx1 : (obj: T, key: K) => void @@ -617,6 +617,16 @@ function fx1(obj: T, key: K) { >obj : NonNullable > : ^^^^^^^^^^^^^^ >key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K > : ^ } @@ -650,6 +660,16 @@ function fx2, K extends keyof T>(obj: T, key: >obj : T > : ^ >key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : T[K] +> : ^^^^ +>obj?.[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K > : ^ } @@ -661,27 +681,223 @@ function fx3 | undefined, K extends keyof T>(o >key : K > : ^ - const x1 = obj[key]; // Error ->x1 : Record[K] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->obj[key] : Record[K] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->obj : Record | undefined -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const x1 = obj[key]; +>x1 : T[K] +> : ^^^^ +>obj[key] : T[K] +> : ^^^^ +>obj : T +> : ^ >key : K > : ^ const x2 = obj && obj[key]; ->x2 : Record[K] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->obj && obj[key] : Record[K] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>x2 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >obj : T > : ^ ->obj[key] : Record[K] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->obj : Record -> : ^^^^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ +} + +function fx4(obj: T, key: K) { +>fx4 : (obj: T, key: K) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x1 = obj[key]; +>x1 : T[K] +> : ^^^^ +>obj[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ +} + +function fx5(obj: T, key: K) { +>fx5 : (obj: T, key: K) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x1 = obj[key]; +>x1 : T[K] +> : ^^^^ +>obj[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ +} + +function fx6(obj: T | null | undefined, key: K) { +>fx6 : (obj: T | null | undefined, key: K) => void +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x1 = obj[key]; // Error +>x1 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ +} + +function fx7(obj: { x: T } | null | undefined, key: K) { +>fx7 : (obj: { x: T; } | null | undefined, key: K) => void +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x1 = obj.x[key]; // Error +>x1 : T[K] +> : ^^^^ +>obj.x[key] : T[K] +> : ^^^^ +>obj.x : T +> : ^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj.x[key]; +>x2 : T[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>obj && obj.x[key] : T[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>obj.x[key] : T[K] +> : ^^^^ +>obj.x : T +> : ^ +>obj : { x: T; } +> : ^^^^^ ^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x3 = obj?.x[key]; +>x3 : T[K] | undefined +> : ^^^^^^^^^^^^^^^^ +>obj?.x[key] : T[K] | undefined +> : ^^^^^^^^^^^^^^^^ +>obj?.x : T | undefined +> : ^^^^^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T | undefined +> : ^^^^^^^^^^^^^ >key : K > : ^ } @@ -706,21 +922,21 @@ class TableBaseEnum< >null! : never > : ^^^^^ - iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined ->iSpec[null! as keyof InternalSpec] : Record[keyof InternalSpec] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->iSpec : Record | undefined -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + iSpec[null! as keyof InternalSpec]; +>iSpec[null! as keyof InternalSpec] : InternalSpec[keyof InternalSpec] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>iSpec : InternalSpec +> : ^^^^^^^^^^^^ >null! as keyof InternalSpec : keyof InternalSpec > : ^^^^^^^^^^^^^^^^^^ >null! : never > : ^^^^^ - iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined ->iSpec[null! as keyof PublicSpec] : Record[keyof PublicSpec] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->iSpec : Record | undefined -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + iSpec[null! as keyof PublicSpec]; // Error +>iSpec[null! as keyof PublicSpec] : any +> : ^^^ +>iSpec : InternalSpec +> : ^^^^^^^^^^^^ >null! as keyof PublicSpec : keyof PublicSpec > : ^^^^^^^^^^^^^^^^ >null! : never @@ -737,20 +953,20 @@ class TableBaseEnum< return; } iSpec[null! as keyof InternalSpec]; ->iSpec[null! as keyof InternalSpec] : Record[keyof InternalSpec] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->iSpec : Record -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>iSpec[null! as keyof InternalSpec] : (InternalSpec & {})[keyof InternalSpec] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>iSpec : InternalSpec & {} +> : ^^^^^^^^^^^^^^^^^ >null! as keyof InternalSpec : keyof InternalSpec > : ^^^^^^^^^^^^^^^^^^ >null! : never > : ^^^^^ iSpec[null! as keyof PublicSpec]; ->iSpec[null! as keyof PublicSpec] : Record[keyof PublicSpec] -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->iSpec : Record -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>iSpec[null! as keyof PublicSpec] : (InternalSpec & {})[keyof PublicSpec] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>iSpec : InternalSpec & {} +> : ^^^^^^^^^^^^^^^^^ >null! as keyof PublicSpec : keyof PublicSpec > : ^^^^^^^^^^^^^^^^ >null! : never diff --git a/tests/baselines/reference/genericUnboundedTypeParamAssignability.errors.txt b/tests/baselines/reference/genericUnboundedTypeParamAssignability.errors.txt index 8dad05aa147fd..eef2f0d6ba0f6 100644 --- a/tests/baselines/reference/genericUnboundedTypeParamAssignability.errors.txt +++ b/tests/baselines/reference/genericUnboundedTypeParamAssignability.errors.txt @@ -1,14 +1,14 @@ -genericUnboundedTypeParamAssignability.ts(2,5): error TS2339: Property 'toString' does not exist on type 'T'. +genericUnboundedTypeParamAssignability.ts(2,3): error TS18049: 'o' is possibly 'null' or 'undefined'. genericUnboundedTypeParamAssignability.ts(15,6): error TS2345: Argument of type 'T' is not assignable to parameter of type '{}'. genericUnboundedTypeParamAssignability.ts(16,6): error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record'. -genericUnboundedTypeParamAssignability.ts(17,5): error TS2339: Property 'toString' does not exist on type 'T'. +genericUnboundedTypeParamAssignability.ts(17,3): error TS18049: 't' is possibly 'null' or 'undefined'. ==== genericUnboundedTypeParamAssignability.ts (4 errors) ==== function f1(o: T) { o.toString(); // error - ~~~~~~~~ -!!! error TS2339: Property 'toString' does not exist on type 'T'. + ~ +!!! error TS18049: 'o' is possibly 'null' or 'undefined'. } function f2(o: T) { @@ -30,7 +30,7 @@ genericUnboundedTypeParamAssignability.ts(17,5): error TS2339: Property 'toStrin !!! error TS2345: Argument of type 'T' is not assignable to parameter of type 'Record'. !!! related TS2208 genericUnboundedTypeParamAssignability.ts:13:15: This type parameter might need an `extends Record` constraint. t.toString(); // error, for the same reason as f1() - ~~~~~~~~ -!!! error TS2339: Property 'toString' does not exist on type 'T'. + ~ +!!! error TS18049: 't' is possibly 'null' or 'undefined'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericUnboundedTypeParamAssignability.symbols b/tests/baselines/reference/genericUnboundedTypeParamAssignability.symbols index 6e5f0187940c6..0125bfed73ff2 100644 --- a/tests/baselines/reference/genericUnboundedTypeParamAssignability.symbols +++ b/tests/baselines/reference/genericUnboundedTypeParamAssignability.symbols @@ -8,7 +8,9 @@ function f1(o: T) { >T : Symbol(T, Decl(genericUnboundedTypeParamAssignability.ts, 0, 12)) o.toString(); // error +>o.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) >o : Symbol(o, Decl(genericUnboundedTypeParamAssignability.ts, 0, 15)) +>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) } function f2(o: T) { @@ -55,6 +57,8 @@ function user(t: T) { >t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17)) t.toString(); // error, for the same reason as f1() +>t.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) >t : Symbol(t, Decl(genericUnboundedTypeParamAssignability.ts, 12, 17)) +>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) } diff --git a/tests/baselines/reference/genericUnboundedTypeParamAssignability.types b/tests/baselines/reference/genericUnboundedTypeParamAssignability.types index 92816a1a292db..54480f3bd9e03 100644 --- a/tests/baselines/reference/genericUnboundedTypeParamAssignability.types +++ b/tests/baselines/reference/genericUnboundedTypeParamAssignability.types @@ -8,14 +8,14 @@ function f1(o: T) { > : ^ o.toString(); // error ->o.toString() : any -> : ^^^ ->o.toString : any -> : ^^^ +>o.toString() : string +> : ^^^^^^ +>o.toString : () => string +> : ^^^^^^ >o : T > : ^ ->toString : any -> : ^^^ +>toString : () => string +> : ^^^^^^ } function f2(o: T) { @@ -83,13 +83,13 @@ function user(t: T) { > : ^ t.toString(); // error, for the same reason as f1() ->t.toString() : any -> : ^^^ ->t.toString : any -> : ^^^ +>t.toString() : string +> : ^^^^^^ +>t.toString : () => string +> : ^^^^^^ >t : T > : ^ ->toString : any -> : ^^^ +>toString : () => string +> : ^^^^^^ } diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt b/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt index 7b998070848b9..f1221aae3e3fd 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt +++ b/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt @@ -30,7 +30,7 @@ inKeywordTypeguard.ts(90,5): error TS2564: Property 'a' has no initializer and i inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'. inKeywordTypeguard.ts(155,16): error TS18046: 'x' is of type 'unknown'. inKeywordTypeguard.ts(158,21): error TS2638: Type '{}' may represent a primitive value, which is not permitted as the right operand of the 'in' operator. -inKeywordTypeguard.ts(183,16): error TS2322: Type 'T' is not assignable to type 'object'. +inKeywordTypeguard.ts(183,16): error TS18049: 'x' is possibly 'null' or 'undefined'. inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNullable' may represent a primitive value, which is not permitted as the right operand of the 'in' operator. @@ -277,8 +277,7 @@ inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNullable' may represent function f3(x: T) { if ("a" in x) { ~ -!!! error TS2322: Type 'T' is not assignable to type 'object'. -!!! related TS2208 inKeywordTypeguard.ts:182:13: This type parameter might need an `extends object` constraint. +!!! error TS18049: 'x' is possibly 'null' or 'undefined'. x.a; } if (x && "a" in x) { diff --git a/tests/baselines/reference/keyofAndIndexedAccess.errors.txt b/tests/baselines/reference/keyofAndIndexedAccess.errors.txt index e833106df6fe5..1d98aaaa2cc39 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.errors.txt +++ b/tests/baselines/reference/keyofAndIndexedAccess.errors.txt @@ -1,10 +1,5 @@ -keyofAndIndexedAccess.ts(205,24): error TS2322: Type 'T[keyof T]' is not assignable to type 'object'. - Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'. - Type 'T[string]' is not assignable to type 'object'. -keyofAndIndexedAccess.ts(211,24): error TS2322: Type 'T[K]' is not assignable to type 'object'. - Type 'T[keyof T]' is not assignable to type 'object'. - Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'. - Type 'T[string]' is not assignable to type 'object'. +keyofAndIndexedAccess.ts(205,24): error TS2533: Object is possibly 'null' or 'undefined'. +keyofAndIndexedAccess.ts(211,24): error TS2533: Object is possibly 'null' or 'undefined'. keyofAndIndexedAccess.ts(316,5): error TS2322: Type 'T' is not assignable to type '{}'. keyofAndIndexedAccess.ts(317,5): error TS2322: Type 'T[keyof T]' is not assignable to type '{}'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'. @@ -222,9 +217,7 @@ keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to } const b = "foo" in obj[key]; ~~~~~~~~ -!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'object'. -!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'. -!!! error TS2322: Type 'T[string]' is not assignable to type 'object'. +!!! error TS2533: Object is possibly 'null' or 'undefined'. } function f55(obj: T, key: K) { @@ -232,10 +225,7 @@ keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to } const b = "foo" in obj[key]; ~~~~~~~~ -!!! error TS2322: Type 'T[K]' is not assignable to type 'object'. -!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'object'. -!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'. -!!! error TS2322: Type 'T[string]' is not assignable to type 'object'. +!!! error TS2533: Object is possibly 'null' or 'undefined'. } function f60(source: T, target: T) { diff --git a/tests/baselines/reference/unconstrainedTypeComparison.errors.txt b/tests/baselines/reference/unconstrainedTypeComparison.errors.txt new file mode 100644 index 0000000000000..611c50724ee76 --- /dev/null +++ b/tests/baselines/reference/unconstrainedTypeComparison.errors.txt @@ -0,0 +1,186 @@ +unconstrainedTypeComparison.ts(2,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(2,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(6,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(6,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(10,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(10,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(14,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(14,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(18,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(18,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(22,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(22,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(26,12): error TS18048: 'a' is possibly 'undefined'. +unconstrainedTypeComparison.ts(26,16): error TS18048: 'b' is possibly 'undefined'. +unconstrainedTypeComparison.ts(30,12): error TS18047: 'a' is possibly 'null'. +unconstrainedTypeComparison.ts(30,16): error TS18047: 'b' is possibly 'null'. +unconstrainedTypeComparison.ts(34,12): error TS18049: 'a' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(34,16): error TS18049: 'b' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(38,12): error TS18049: 'x' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(38,16): error TS18049: 'y' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(42,12): error TS18049: 'x' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(42,16): error TS18049: 'y' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(49,12): error TS18047: 'x' is possibly 'null'. +unconstrainedTypeComparison.ts(49,16): error TS18049: 'y' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(56,12): error TS18047: 'x' is possibly 'null'. +unconstrainedTypeComparison.ts(56,16): error TS18049: 'y' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(60,12): error TS18049: 'x' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(60,16): error TS18049: 'y' is possibly 'null' or 'undefined'. +unconstrainedTypeComparison.ts(74,12): error TS18047: 'x' is possibly 'null'. +unconstrainedTypeComparison.ts(74,16): error TS18048: 'y' is possibly 'undefined'. +unconstrainedTypeComparison.ts(85,12): error TS18047: 'a' is possibly 'null'. +unconstrainedTypeComparison.ts(85,16): error TS18048: 'b' is possibly 'undefined'. + + +==== unconstrainedTypeComparison.ts (32 errors) ==== + function f1(a: T, b: T): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f2(a: T, b: T): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f3(a: T, b: T): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f4(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f5(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f6(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f7(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18048: 'a' is possibly 'undefined'. + ~ +!!! error TS18048: 'b' is possibly 'undefined'. + } + + function f8(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18047: 'a' is possibly 'null'. + ~ +!!! error TS18047: 'b' is possibly 'null'. + } + + function f9(a: U, b: U): boolean { + return a > b; + ~ +!!! error TS18049: 'a' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'b' is possibly 'null' or 'undefined'. + } + + function f10(x: T | U, y: T | U) { + return x < y; + ~ +!!! error TS18049: 'x' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'y' is possibly 'null' or 'undefined'. + } + + function f11(x: T | number, y: U | number) { + return x < y; + ~ +!!! error TS18049: 'x' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'y' is possibly 'null' or 'undefined'. + } + + function f12(x: T | number, y: U | number) { + if (x === undefined) { + return false; + } + return x < y; + ~ +!!! error TS18047: 'x' is possibly 'null'. + ~ +!!! error TS18049: 'y' is possibly 'null' or 'undefined'. + } + + function f13(x: U, y: U) { + if (x === undefined) { + return false; + } + return x < y; + ~ +!!! error TS18047: 'x' is possibly 'null'. + ~ +!!! error TS18049: 'y' is possibly 'null' or 'undefined'. + } + + function f14(x: T & U, y: T & U) { + return x < y; + ~ +!!! error TS18049: 'x' is possibly 'null' or 'undefined'. + ~ +!!! error TS18049: 'y' is possibly 'null' or 'undefined'. + } + + function f15(x: T & number, y: U & number) { + return x < y; + } + + function f16(x: T & U, y: U) { + if (x === undefined) { + return false; + } + if (y === null) { + return false; + } + return x < y; + ~ +!!! error TS18047: 'x' is possibly 'null'. + ~ +!!! error TS18048: 'y' is possibly 'undefined'. + } + + + function compare(a: T, b: T): boolean { + if (a === undefined) { + return false; + } + if (b === null) { + return false; + } + return a > b; + ~ +!!! error TS18047: 'a' is possibly 'null'. + ~ +!!! error TS18048: 'b' is possibly 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/unconstrainedTypeComparison.symbols b/tests/baselines/reference/unconstrainedTypeComparison.symbols new file mode 100644 index 0000000000000..10417838d9fcd --- /dev/null +++ b/tests/baselines/reference/unconstrainedTypeComparison.symbols @@ -0,0 +1,288 @@ +//// [tests/cases/compiler/unconstrainedTypeComparison.ts] //// + +=== unconstrainedTypeComparison.ts === +function f1(a: T, b: T): boolean { +>f1 : Symbol(f1, Decl(unconstrainedTypeComparison.ts, 0, 0)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 0, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 0, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 0, 12)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 0, 20)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 0, 12)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 0, 15)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 0, 20)) +} + +function f2(a: T, b: T): boolean { +>f2 : Symbol(f2, Decl(unconstrainedTypeComparison.ts, 2, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 4, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 4, 45)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 4, 12)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 4, 50)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 4, 12)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 4, 45)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 4, 50)) +} + +function f3(a: T, b: T): boolean { +>f3 : Symbol(f3, Decl(unconstrainedTypeComparison.ts, 6, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 8, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 8, 31)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 8, 12)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 8, 36)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 8, 12)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 8, 31)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 8, 36)) +} + +function f4(a: U, b: U): boolean { +>f4 : Symbol(f4, Decl(unconstrainedTypeComparison.ts, 10, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 12, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 12, 14)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 12, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 12, 28)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 12, 14)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 12, 33)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 12, 14)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 12, 28)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 12, 33)) +} + +function f5(a: U, b: U): boolean { +>f5 : Symbol(f5, Decl(unconstrainedTypeComparison.ts, 14, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 16, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 16, 44)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 16, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 16, 58)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 16, 44)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 16, 63)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 16, 44)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 16, 58)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 16, 63)) +} + +function f6(a: U, b: U): boolean { +>f6 : Symbol(f6, Decl(unconstrainedTypeComparison.ts, 18, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 20, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 20, 30)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 20, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 20, 44)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 20, 30)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 20, 49)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 20, 30)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 20, 44)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 20, 49)) +} + +function f7(a: U, b: U): boolean { +>f7 : Symbol(f7, Decl(unconstrainedTypeComparison.ts, 22, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 24, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 24, 37)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 24, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 24, 51)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 24, 37)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 24, 56)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 24, 37)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 24, 51)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 24, 56)) +} + +function f8(a: U, b: U): boolean { +>f8 : Symbol(f8, Decl(unconstrainedTypeComparison.ts, 26, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 28, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 28, 32)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 28, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 28, 46)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 28, 32)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 28, 51)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 28, 32)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 28, 46)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 28, 51)) +} + +function f9(a: U, b: U): boolean { +>f9 : Symbol(f9, Decl(unconstrainedTypeComparison.ts, 30, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 32, 12)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 32, 39)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 32, 12)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 32, 53)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 32, 39)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 32, 58)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 32, 39)) + + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 32, 53)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 32, 58)) +} + +function f10(x: T | U, y: T | U) { +>f10 : Symbol(f10, Decl(unconstrainedTypeComparison.ts, 34, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 36, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 36, 15)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 36, 19)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 36, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 36, 15)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 36, 28)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 36, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 36, 15)) + + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 36, 19)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 36, 28)) +} + +function f11(x: T | number, y: U | number) { +>f11 : Symbol(f11, Decl(unconstrainedTypeComparison.ts, 38, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 40, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 40, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 40, 13)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 40, 29)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 40, 13)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 40, 43)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 40, 15)) + + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 40, 29)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 40, 43)) +} + +function f12(x: T | number, y: U | number) { +>f12 : Symbol(f12, Decl(unconstrainedTypeComparison.ts, 42, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 44, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 44, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 44, 13)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 44, 29)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 44, 13)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 44, 43)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 44, 15)) + + if (x === undefined) { +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 44, 29)) +>undefined : Symbol(undefined) + + return false; + } + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 44, 29)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 44, 43)) +} + +function f13(x: U, y: U) { +>f13 : Symbol(f13, Decl(unconstrainedTypeComparison.ts, 49, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 51, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 51, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 51, 13)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 51, 38)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 51, 15)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 51, 43)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 51, 15)) + + if (x === undefined) { +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 51, 38)) +>undefined : Symbol(undefined) + + return false; + } + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 51, 38)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 51, 43)) +} + +function f14(x: T & U, y: T & U) { +>f14 : Symbol(f14, Decl(unconstrainedTypeComparison.ts, 56, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 58, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 58, 15)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 58, 19)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 58, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 58, 15)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 58, 28)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 58, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 58, 15)) + + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 58, 19)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 58, 28)) +} + +function f15(x: T & number, y: U & number) { +>f15 : Symbol(f15, Decl(unconstrainedTypeComparison.ts, 60, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 62, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 62, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 62, 13)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 62, 29)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 62, 13)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 62, 43)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 62, 15)) + + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 62, 29)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 62, 43)) +} + +function f16(x: T & U, y: U) { +>f16 : Symbol(f16, Decl(unconstrainedTypeComparison.ts, 64, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 66, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 66, 15)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 66, 13)) +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 66, 29)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 66, 13)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 66, 15)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 66, 38)) +>U : Symbol(U, Decl(unconstrainedTypeComparison.ts, 66, 15)) + + if (x === undefined) { +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 66, 29)) +>undefined : Symbol(undefined) + + return false; + } + if (y === null) { +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 66, 38)) + + return false; + } + return x < y; +>x : Symbol(x, Decl(unconstrainedTypeComparison.ts, 66, 29)) +>y : Symbol(y, Decl(unconstrainedTypeComparison.ts, 66, 38)) +} + + +function compare(a: T, b: T): boolean { +>compare : Symbol(compare, Decl(unconstrainedTypeComparison.ts, 74, 1)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 77, 17)) +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 77, 20)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 77, 17)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 77, 25)) +>T : Symbol(T, Decl(unconstrainedTypeComparison.ts, 77, 17)) + + if (a === undefined) { +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 77, 20)) +>undefined : Symbol(undefined) + + return false; + } + if (b === null) { +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 77, 25)) + + return false; + } + return a > b; +>a : Symbol(a, Decl(unconstrainedTypeComparison.ts, 77, 20)) +>b : Symbol(b, Decl(unconstrainedTypeComparison.ts, 77, 25)) +} + diff --git a/tests/baselines/reference/unconstrainedTypeComparison.types b/tests/baselines/reference/unconstrainedTypeComparison.types new file mode 100644 index 0000000000000..5580397de2af8 --- /dev/null +++ b/tests/baselines/reference/unconstrainedTypeComparison.types @@ -0,0 +1,361 @@ +//// [tests/cases/compiler/unconstrainedTypeComparison.ts] //// + +=== unconstrainedTypeComparison.ts === +function f1(a: T, b: T): boolean { +>f1 : (a: T, b: T) => boolean +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>a : T +> : ^ +>b : T +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : T +> : ^ +>b : T +> : ^ +} + +function f2(a: T, b: T): boolean { +>f2 : (a: T, b: T) => boolean +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : T +> : ^ +>b : T +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : T +> : ^ +>b : T +> : ^ +} + +function f3(a: T, b: T): boolean { +>f3 : (a: T, b: T) => boolean +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : T +> : ^ +>b : T +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : T +> : ^ +>b : T +> : ^ +} + +function f4(a: U, b: U): boolean { +>f4 : (a: U, b: U) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f5(a: U, b: U): boolean { +>f5 : (a: U, b: U) => boolean +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f6(a: U, b: U): boolean { +>f6 : (a: U, b: U) => boolean +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f7(a: U, b: U): boolean { +>f7 : (a: U, b: U) => boolean +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f8(a: U, b: U): boolean { +>f8 : (a: U, b: U) => boolean +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f9(a: U, b: U): boolean { +>f9 : (a: U, b: U) => boolean +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>a : U +> : ^ +>b : U +> : ^ + + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : U +> : ^ +>b : U +> : ^ +} + +function f10(x: T | U, y: T | U) { +>f10 : (x: T | U, y: T | U) => boolean +> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : T | U +> : ^^^^^ +>y : T | U +> : ^^^^^ + + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : T | U +> : ^^^^^ +>y : T | U +> : ^^^^^ +} + +function f11(x: T | number, y: U | number) { +>f11 : (x: T | number, y: U | number) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : number | T +> : ^^^^^^^^^^ +>y : number | U +> : ^^^^^^^^^^ + + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : number | T +> : ^^^^^^^^^^ +>y : number | U +> : ^^^^^^^^^^ +} + +function f12(x: T | number, y: U | number) { +>f12 : (x: T | number, y: U | number) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : number | T +> : ^^^^^^^^^^ +>y : number | U +> : ^^^^^^^^^^ + + if (x === undefined) { +>x === undefined : boolean +> : ^^^^^^^ +>x : number | T +> : ^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + return false; +>false : false +> : ^^^^^ + } + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : number | (T & ({} | null)) +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>y : number | U +> : ^^^^^^^^^^ +} + +function f13(x: U, y: U) { +>f13 : (x: U, y: U) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : U +> : ^ +>y : U +> : ^ + + if (x === undefined) { +>x === undefined : boolean +> : ^^^^^^^ +>x : U +> : ^ +>undefined : undefined +> : ^^^^^^^^^ + + return false; +>false : false +> : ^^^^^ + } + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : U & ({} | null) +> : ^^^^^^^^^^^^^^^ +>y : U +> : ^ +} + +function f14(x: T & U, y: T & U) { +>f14 : (x: T & U, y: T & U) => boolean +> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : T & U +> : ^^^^^ +>y : T & U +> : ^^^^^ + + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : T & U +> : ^^^^^ +>y : T & U +> : ^^^^^ +} + +function f15(x: T & number, y: U & number) { +>f15 : (x: T & number, y: U & number) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : T & number +> : ^^^^^^^^^^ +>y : U & number +> : ^^^^^^^^^^ + + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : T & number +> : ^^^^^^^^^^ +>y : U & number +> : ^^^^^^^^^^ +} + +function f16(x: T & U, y: U) { +>f16 : (x: T & U, y: U) => boolean +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^ +>x : T & U +> : ^^^^^ +>y : U +> : ^ + + if (x === undefined) { +>x === undefined : boolean +> : ^^^^^^^ +>x : T & U +> : ^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + return false; +>false : false +> : ^^^^^ + } + if (y === null) { +>y === null : boolean +> : ^^^^^^^ +>y : U +> : ^ + + return false; +>false : false +> : ^^^^^ + } + return x < y; +>x < y : boolean +> : ^^^^^^^ +>x : T & U & ({} | null) +> : ^^^^^^^^^^^^^^^^^^^ +>y : U & ({} | undefined) +> : ^^^^^^^^^^^^^^^^^^^^ +} + + +function compare(a: T, b: T): boolean { +>compare : (a: T, b: T) => boolean +> : ^ ^^ ^^ ^^ ^^ ^^^^^ +>a : T +> : ^ +>b : T +> : ^ + + if (a === undefined) { +>a === undefined : boolean +> : ^^^^^^^ +>a : T +> : ^ +>undefined : undefined +> : ^^^^^^^^^ + + return false; +>false : false +> : ^^^^^ + } + if (b === null) { +>b === null : boolean +> : ^^^^^^^ +>b : T +> : ^ + + return false; +>false : false +> : ^^^^^ + } + return a > b; +>a > b : boolean +> : ^^^^^^^ +>a : T & ({} | null) +> : ^^^^^^^^^^^^^^^ +>b : T & ({} | undefined) +> : ^^^^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/cases/compiler/unconstrainedTypeComparison.ts b/tests/cases/compiler/unconstrainedTypeComparison.ts new file mode 100644 index 0000000000000..e542e481a4247 --- /dev/null +++ b/tests/cases/compiler/unconstrainedTypeComparison.ts @@ -0,0 +1,89 @@ +// @strict: true +// @noemit: true + +function f1(a: T, b: T): boolean { + return a > b; +} + +function f2(a: T, b: T): boolean { + return a > b; +} + +function f3(a: T, b: T): boolean { + return a > b; +} + +function f4(a: U, b: U): boolean { + return a > b; +} + +function f5(a: U, b: U): boolean { + return a > b; +} + +function f6(a: U, b: U): boolean { + return a > b; +} + +function f7(a: U, b: U): boolean { + return a > b; +} + +function f8(a: U, b: U): boolean { + return a > b; +} + +function f9(a: U, b: U): boolean { + return a > b; +} + +function f10(x: T | U, y: T | U) { + return x < y; +} + +function f11(x: T | number, y: U | number) { + return x < y; +} + +function f12(x: T | number, y: U | number) { + if (x === undefined) { + return false; + } + return x < y; +} + +function f13(x: U, y: U) { + if (x === undefined) { + return false; + } + return x < y; +} + +function f14(x: T & U, y: T & U) { + return x < y; +} + +function f15(x: T & number, y: U & number) { + return x < y; +} + +function f16(x: T & U, y: U) { + if (x === undefined) { + return false; + } + if (y === null) { + return false; + } + return x < y; +} + + +function compare(a: T, b: T): boolean { + if (a === undefined) { + return false; + } + if (b === null) { + return false; + } + return a > b; +} diff --git a/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts b/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts index 50c2c4fdf147e..d4dcd885a4516 100644 --- a/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts +++ b/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts @@ -140,23 +140,50 @@ function once>(emittingObject: T, eventName: keyo emittingObject.off(eventName as typeof eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx6(obj: T | null | undefined, key: K) { const x1 = obj[key]; // Error const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166 @@ -166,8 +193,8 @@ class TableBaseEnum< InternalSpec extends Record | undefined = undefined> { m() { let iSpec = null! as InternalSpec; - iSpec[null! as keyof InternalSpec]; // Error, object possibly undefined - iSpec[null! as keyof PublicSpec]; // Error, object possibly undefined + iSpec[null! as keyof InternalSpec]; + iSpec[null! as keyof PublicSpec]; // Error if (iSpec === undefined) { return; }