Skip to content

Commit 3c243db

Browse files
committed
Remove control flow-based undefined addition
Just add undefined when displaying the type. Don't actually add it to the type.
1 parent 01a9e4f commit 3c243db

File tree

3 files changed

+46
-76
lines changed

3 files changed

+46
-76
lines changed

src/compiler/binder.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -822,15 +822,6 @@ namespace ts {
822822
};
823823
}
824824

825-
function createFlowInitializedParameter(antecedent: FlowNode, node: ParameterDeclaration): FlowNode {
826-
setFlowNodeReferenced(antecedent);
827-
return <FlowInitializedParameter>{
828-
flags: FlowFlags.InitializedParameter,
829-
antecedent,
830-
node
831-
};
832-
}
833-
834825
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
835826
setFlowNodeReferenced(antecedent);
836827
return <FlowArrayMutation>{
@@ -2328,9 +2319,6 @@ namespace ts {
23282319
}
23292320
else {
23302321
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
2331-
if (node.initializer) {
2332-
currentFlow = createFlowInitializedParameter(currentFlow, node);
2333-
}
23342322
}
23352323

23362324
// If this is a property-parameter, then also declare the property symbol into the

src/compiler/checker.ts

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,7 +2694,11 @@ namespace ts {
26942694
writePunctuation(writer, SyntaxKind.ColonToken);
26952695
writeSpace(writer);
26962696

2697-
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack);
2697+
let type = getTypeOfSymbol(p);
2698+
if (strictNullChecks && parameterNode.initializer && !(getModifierFlags(parameterNode) & ModifierFlags.ParameterPropertyModifier)) {
2699+
type = includeFalsyTypes(type, TypeFlags.Undefined);
2700+
}
2701+
buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
26982702
}
26992703

27002704
function buildBindingPatternDisplay(bindingPattern: BindingPattern, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
@@ -3315,9 +3319,7 @@ namespace ts {
33153319

33163320
// Use type from type annotation if one is present
33173321
if (declaration.type) {
3318-
const isOptional = declaration.questionToken ||
3319-
(declaration.initializer && declaration.kind === SyntaxKind.Parameter && !(getModifierFlags(declaration) & ModifierFlags.ParameterPropertyModifier));
3320-
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ isOptional && includeOptionality);
3322+
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
33213323
}
33223324

33233325
if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
@@ -3368,10 +3370,7 @@ namespace ts {
33683370
// Use the type of the initializer expression if one is present
33693371
if (declaration.initializer) {
33703372
const type = checkDeclarationInitializer(declaration);
3371-
// initialized parameters (but not parameter properties) are optional
3372-
const isOptional = declaration.questionToken ||
3373-
(declaration.kind === SyntaxKind.Parameter && !(getModifierFlags(declaration) & ModifierFlags.ParameterPropertyModifier));
3374-
return addOptionality(type, isOptional && includeOptionality);
3373+
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
33753374
}
33763375

33773376
// If it is a short-hand property assignment, use the type of the identifier
@@ -7101,8 +7100,8 @@ namespace ts {
71017100
const sourceParams = source.parameters;
71027101
const targetParams = target.parameters;
71037102
for (let i = 0; i < checkCount; i++) {
7104-
const s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source);
7105-
const t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target);
7103+
const s = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source);
7104+
const t = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target);
71067105
const related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors);
71077106
if (!related) {
71087107
if (reportErrors) {
@@ -8299,8 +8298,8 @@ namespace ts {
82998298

83008299
const targetLen = target.parameters.length;
83018300
for (let i = 0; i < targetLen; i++) {
8302-
const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
8303-
const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
8301+
const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfParameter(source.parameters[i]);
8302+
const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfParameter(target.parameters[i]);
83048303
const related = compareTypes(s, t);
83058304
if (!related) {
83068305
return Ternary.False;
@@ -9196,8 +9195,8 @@ namespace ts {
91969195
switch (source.kind) {
91979196
case SyntaxKind.Identifier:
91989197
return target.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>source) === getResolvedSymbol(<Identifier>target) ||
9199-
(target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement || target.kind === SyntaxKind.Parameter) &&
9200-
getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfNode(target);
9198+
(target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) &&
9199+
getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>source)) === getSymbolOfNode(target);
92019200
case SyntaxKind.ThisKeyword:
92029201
return target.kind === SyntaxKind.ThisKeyword;
92039202
case SyntaxKind.PropertyAccessExpression:
@@ -9291,13 +9290,6 @@ namespace ts {
92919290
return false;
92929291
}
92939292

9294-
function getInitializedParameterReducedType(declaredType: UnionType, assignedType: Type) {
9295-
if (declaredType === assignedType || getFalsyFlags(assignedType) & TypeFlags.Undefined) {
9296-
return declaredType;
9297-
}
9298-
return getTypeWithFacts(declaredType, TypeFacts.NEUndefined);
9299-
}
9300-
93019293
// Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
93029294
// For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
93039295
// we remove type string.
@@ -9478,7 +9470,7 @@ namespace ts {
94789470
return links.resolvedType || getTypeOfExpression(node);
94799471
}
94809472

9481-
function getInitialTypeOfVariableDeclaration(node: VariableDeclaration | ParameterDeclaration) {
9473+
function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) {
94829474
if (node.initializer) {
94839475
return getTypeOfInitializer(node.initializer);
94849476
}
@@ -9491,15 +9483,15 @@ namespace ts {
94919483
return unknownType;
94929484
}
94939485

9494-
function getInitialType(node: VariableDeclaration | BindingElement | ParameterDeclaration) {
9495-
return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.Parameter ?
9496-
getInitialTypeOfVariableDeclaration(<VariableDeclaration | ParameterDeclaration>node) :
9486+
function getInitialType(node: VariableDeclaration | BindingElement) {
9487+
return node.kind === SyntaxKind.VariableDeclaration ?
9488+
getInitialTypeOfVariableDeclaration(<VariableDeclaration>node) :
94979489
getInitialTypeOfBindingElement(<BindingElement>node);
94989490
}
94999491

9500-
function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression | ParameterDeclaration) {
9501-
return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement || node.kind === SyntaxKind.Parameter ?
9502-
getInitialType(<VariableDeclaration | BindingElement | ParameterDeclaration>node) :
9492+
function getInitialOrAssignedType(node: VariableDeclaration | BindingElement | Expression) {
9493+
return node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ?
9494+
getInitialType(<VariableDeclaration | BindingElement>node) :
95039495
getAssignedType(<Expression>node);
95049496
}
95059497

@@ -9768,13 +9760,6 @@ namespace ts {
97689760
continue;
97699761
}
97709762
}
9771-
else if (flow.flags & FlowFlags.InitializedParameter) {
9772-
type = getTypeAtFlowInitializedParameter(flow as FlowInitializedParameter);
9773-
if (!type) {
9774-
flow = (flow as FlowInitializedParameter).antecedent;
9775-
continue;
9776-
}
9777-
}
97789763
else if (flow.flags & FlowFlags.Condition) {
97799764
type = getTypeAtFlowCondition(<FlowCondition>flow);
97809765
}
@@ -9822,20 +9807,6 @@ namespace ts {
98229807
}
98239808
}
98249809

9825-
function getTypeAtFlowInitializedParameter(flow: FlowInitializedParameter) {
9826-
const node = flow.node;
9827-
// Parameter initializers don't really narrow the declared type except to remove undefined.
9828-
// If the initializer includes undefined in the type, it doesn't even remove undefined.
9829-
if (isMatchingReference(reference, node)) {
9830-
if (declaredType.flags & TypeFlags.Union) {
9831-
return getInitializedParameterReducedType(<UnionType>declaredType, getInitialOrAssignedType(node));
9832-
}
9833-
return declaredType;
9834-
}
9835-
9836-
return undefined;
9837-
}
9838-
98399810
function getTypeAtFlowAssignment(flow: FlowAssignment) {
98409811
const node = flow.node;
98419812
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
@@ -14033,10 +14004,21 @@ namespace ts {
1403314004
}
1403414005
}
1403514006

14007+
function getTypeOfParameter(symbol: Symbol) {
14008+
const type = getTypeOfSymbol(symbol);
14009+
if (strictNullChecks) {
14010+
const declaration = symbol.valueDeclaration;
14011+
if (declaration && (<VariableLikeDeclaration>declaration).initializer) {
14012+
return includeFalsyTypes(type, TypeFlags.Undefined);
14013+
}
14014+
}
14015+
return type;
14016+
}
14017+
1403614018
function getTypeAtPosition(signature: Signature, pos: number): Type {
1403714019
return signature.hasRestParameter ?
14038-
pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
14039-
pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType;
14020+
pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
14021+
pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType;
1404014022
}
1404114023

1404214024
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
@@ -20652,9 +20634,15 @@ namespace ts {
2065220634
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
2065320635
// Get type of the symbol if this is the valid symbol otherwise get type at location
2065420636
const symbol = getSymbolOfNode(declaration);
20655-
const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
20637+
let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
2065620638
? getWidenedLiteralType(getTypeOfSymbol(symbol))
2065720639
: unknownType;
20640+
if (strictNullChecks &&
20641+
declaration.kind === SyntaxKind.Parameter &&
20642+
(declaration as ParameterDeclaration).initializer &&
20643+
!(getModifierFlags(declaration) & ModifierFlags.ParameterPropertyModifier)) {
20644+
type = includeFalsyTypes(type, TypeFlags.Undefined);
20645+
}
2065820646

2065920647
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
2066020648
}

src/compiler/types.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,13 +2062,12 @@
20622062
BranchLabel = 1 << 2, // Non-looping junction
20632063
LoopLabel = 1 << 3, // Looping junction
20642064
Assignment = 1 << 4, // Assignment
2065-
InitializedParameter = 1 << 5, // Parameter with initializer
2066-
TrueCondition = 1 << 6, // Condition known to be true
2067-
FalseCondition = 1 << 7, // Condition known to be false
2068-
SwitchClause = 1 << 8, // Switch statement clause
2069-
ArrayMutation = 1 << 9, // Potential array mutation
2070-
Referenced = 1 << 10, // Referenced as antecedent once
2071-
Shared = 1 << 11, // Referenced as antecedent more than once
2065+
TrueCondition = 1 << 5, // Condition known to be true
2066+
FalseCondition = 1 << 6, // Condition known to be false
2067+
SwitchClause = 1 << 7, // Switch statement clause
2068+
ArrayMutation = 1 << 8, // Potential array mutation
2069+
Referenced = 1 << 9, // Referenced as antecedent once
2070+
Shared = 1 << 10, // Referenced as antecedent more than once
20722071
Label = BranchLabel | LoopLabel,
20732072
Condition = TrueCondition | FalseCondition
20742073
}
@@ -2118,11 +2117,6 @@
21182117
antecedent: FlowNode;
21192118
}
21202119

2121-
export interface FlowInitializedParameter extends FlowNode {
2122-
node: ParameterDeclaration;
2123-
antecedent: FlowNode;
2124-
}
2125-
21262120
export type FlowType = Type | IncompleteType;
21272121

21282122
// Incomplete types occur during control flow analysis of loops. An IncompleteType

0 commit comments

Comments
 (0)