mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-19 08:24:15 -06:00
Improve typing of && operator with --strictNullChecks
This commit is contained in:
parent
3853555b49
commit
bcc9220451
@ -2844,7 +2844,7 @@ namespace ts {
|
||||
}
|
||||
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
|
||||
// undefined from the final type.
|
||||
if (strictNullChecks && declaration.initializer && !(getNullableKind(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
|
||||
if (strictNullChecks && declaration.initializer && !(getCombinedTypeFlags(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
|
||||
type = getTypeWithFacts(type, TypeFacts.NEUndefined);
|
||||
}
|
||||
return type;
|
||||
@ -2887,7 +2887,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addOptionality(type: Type, optional: boolean): Type {
|
||||
return strictNullChecks && optional ? addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
return strictNullChecks && optional ? addTypeKind(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
@ -3222,7 +3222,7 @@ namespace ts {
|
||||
if (!links.type) {
|
||||
const type = createObjectType(TypeFlags.Anonymous, symbol);
|
||||
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
|
||||
addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
addTypeKind(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
@ -6746,7 +6746,7 @@ namespace ts {
|
||||
return getUnionType(types);
|
||||
}
|
||||
const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined);
|
||||
return supertype && addNullableKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable);
|
||||
return supertype && addTypeKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable);
|
||||
}
|
||||
|
||||
function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void {
|
||||
@ -6817,28 +6817,22 @@ namespace ts {
|
||||
return !!(type.flags & TypeFlags.Tuple);
|
||||
}
|
||||
|
||||
function getNullableKind(type: Type): TypeFlags {
|
||||
let flags = type.flags;
|
||||
if (flags & TypeFlags.Union) {
|
||||
for (const t of (type as UnionType).types) {
|
||||
flags |= t.flags;
|
||||
}
|
||||
}
|
||||
return flags & TypeFlags.Nullable;
|
||||
function getCombinedTypeFlags(type: Type): TypeFlags {
|
||||
return type.flags & TypeFlags.Union ? getCombinedFlagsOfTypes((<UnionType>type).types) : type.flags;
|
||||
}
|
||||
|
||||
function addNullableKind(type: Type, kind: TypeFlags): Type {
|
||||
if ((getNullableKind(type) & kind) !== kind) {
|
||||
const types = [type];
|
||||
if (kind & TypeFlags.Undefined) {
|
||||
types.push(undefinedType);
|
||||
}
|
||||
if (kind & TypeFlags.Null) {
|
||||
types.push(nullType);
|
||||
}
|
||||
type = getUnionType(types);
|
||||
function addTypeKind(type: Type, kind: TypeFlags) {
|
||||
if ((getCombinedTypeFlags(type) & kind) === kind) {
|
||||
return type;
|
||||
}
|
||||
return type;
|
||||
const types = [type];
|
||||
if (kind & TypeFlags.String) types.push(stringType);
|
||||
if (kind & TypeFlags.Number) types.push(numberType);
|
||||
if (kind & TypeFlags.Boolean) types.push(booleanType);
|
||||
if (kind & TypeFlags.Void) types.push(voidType);
|
||||
if (kind & TypeFlags.Undefined) types.push(undefinedType);
|
||||
if (kind & TypeFlags.Null) types.push(nullType);
|
||||
return getUnionType(types);
|
||||
}
|
||||
|
||||
function getNonNullableType(type: Type): Type {
|
||||
@ -7667,7 +7661,7 @@ namespace ts {
|
||||
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
|
||||
return declaredType;
|
||||
}
|
||||
const initialType = assumeInitialized ? declaredType : addNullableKind(declaredType, TypeFlags.Undefined);
|
||||
const initialType = assumeInitialized ? declaredType : addTypeKind(declaredType, TypeFlags.Undefined);
|
||||
const visitedFlowStart = visitedFlowCount;
|
||||
const result = getTypeAtFlowNode(reference.flowNode);
|
||||
visitedFlowCount = visitedFlowStart;
|
||||
@ -8163,7 +8157,7 @@ namespace ts {
|
||||
getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
|
||||
!isDeclarationIncludedInFlow(node, declaration, includeOuterFunctions);
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, includeOuterFunctions);
|
||||
if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
|
||||
if (!assumeInitialized && !(getCombinedTypeFlags(type) & TypeFlags.Undefined) && getCombinedTypeFlags(flowType) & TypeFlags.Undefined) {
|
||||
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
// Return the declared type to reduce follow-on errors
|
||||
return type;
|
||||
@ -9945,7 +9939,7 @@ namespace ts {
|
||||
function checkNonNullExpression(node: Expression | QualifiedName) {
|
||||
const type = checkExpression(node);
|
||||
if (strictNullChecks) {
|
||||
const kind = getNullableKind(type);
|
||||
const kind = getCombinedTypeFlags(type) & TypeFlags.Nullable;
|
||||
if (kind) {
|
||||
error(node, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ?
|
||||
Diagnostics.Object_is_possibly_null_or_undefined :
|
||||
@ -11485,7 +11479,7 @@ namespace ts {
|
||||
if (strictNullChecks) {
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && (<VariableLikeDeclaration>declaration).initializer) {
|
||||
return addNullableKind(type, TypeFlags.Undefined);
|
||||
return addTypeKind(type, TypeFlags.Undefined);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
@ -12411,7 +12405,7 @@ namespace ts {
|
||||
case SyntaxKind.InKeyword:
|
||||
return checkInExpression(left, right, leftType, rightType);
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
return strictNullChecks ? addNullableKind(rightType, getNullableKind(leftType)) : rightType;
|
||||
return strictNullChecks ? addTypeKind(rightType, getCombinedTypeFlags(leftType) & TypeFlags.Falsy) : rightType;
|
||||
case SyntaxKind.BarBarToken:
|
||||
return getUnionType([getNonNullableType(leftType), rightType]);
|
||||
case SyntaxKind.EqualsToken:
|
||||
|
||||
@ -2209,6 +2209,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
Nullable = Undefined | Null,
|
||||
Falsy = String | Number | Boolean | Void | Undefined | Null,
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never,
|
||||
/* @internal */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user