mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-18 05:43:11 -05:00
Fix definite assignment analysis issue caused by x !== null checks (#49387)
* Check for non-intersected `undefined` type in definite assignment analysis * Add regression test
This commit is contained in:
@@ -87,8 +87,8 @@ namespace ts {
|
||||
NEUndefinedOrNull = 1 << 21, // x != undefined / x != null
|
||||
Truthy = 1 << 22, // x
|
||||
Falsy = 1 << 23, // !x
|
||||
IsUndefined = 1 << 24, // Exactly undefined
|
||||
IsNull = 1 << 25, // Exactly null
|
||||
IsUndefined = 1 << 24, // Contains undefined or intersection with undefined
|
||||
IsNull = 1 << 25, // Contains null or intersection with null
|
||||
IsUndefinedOrNull = IsUndefined | IsNull,
|
||||
All = (1 << 27) - 1,
|
||||
// The following members encode facts about particular kinds of types for use in the getTypeFacts function.
|
||||
@@ -18166,6 +18166,10 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function containsUndefinedType(type: Type) {
|
||||
return !!((type.flags & TypeFlags.Union ? (type as UnionType).types[0] : type).flags & TypeFlags.Undefined);
|
||||
}
|
||||
|
||||
function isStringIndexSignatureOnlyType(type: Type): boolean {
|
||||
return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) ||
|
||||
@@ -25911,7 +25915,7 @@ namespace ts {
|
||||
return convertAutoToAny(flowType);
|
||||
}
|
||||
}
|
||||
else if (!assumeInitialized && !(getTypeFacts(type) & TypeFacts.IsUndefined) && getTypeFacts(flowType) & TypeFacts.IsUndefined) {
|
||||
else if (!assumeInitialized && !containsUndefinedType(type) && containsUndefinedType(flowType)) {
|
||||
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
// Return the declared type to reduce follow-on errors
|
||||
return type;
|
||||
@@ -29268,7 +29272,7 @@ namespace ts {
|
||||
assumeUninitialized = true;
|
||||
}
|
||||
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
|
||||
if (assumeUninitialized && !(getTypeFacts(propType) & TypeFacts.IsUndefined) && getTypeFacts(flowType) & TypeFacts.IsUndefined) {
|
||||
if (assumeUninitialized && !containsUndefinedType(propType) && containsUndefinedType(flowType)) {
|
||||
error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
|
||||
// Return the declared type to reduce follow-on errors
|
||||
return propType;
|
||||
@@ -40255,7 +40259,7 @@ namespace ts {
|
||||
const propName = (member as PropertyDeclaration).name;
|
||||
if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) {
|
||||
const type = getTypeOfSymbol(getSymbolOfNode(member));
|
||||
if (!(type.flags & TypeFlags.AnyOrUnknown || getTypeFacts(type) & TypeFacts.IsUndefined)) {
|
||||
if (!(type.flags & TypeFlags.AnyOrUnknown || containsUndefinedType(type))) {
|
||||
if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
|
||||
error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName));
|
||||
}
|
||||
@@ -40281,7 +40285,7 @@ namespace ts {
|
||||
setParent(reference, staticBlock);
|
||||
reference.flowNode = staticBlock.returnFlowNode;
|
||||
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
|
||||
if (!(getTypeFacts(flowType) & TypeFacts.IsUndefined)) {
|
||||
if (!containsUndefinedType(flowType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -40297,7 +40301,7 @@ namespace ts {
|
||||
setParent(reference, constructor);
|
||||
reference.flowNode = constructor.returnFlowNode;
|
||||
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
|
||||
return !(getTypeFacts(flowType) & TypeFacts.IsUndefined);
|
||||
return !containsUndefinedType(flowType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user