@@ -2696,7 +2696,11 @@ namespace ts {
2696
2696
writePunctuation(writer, SyntaxKind.ColonToken);
2697
2697
writeSpace(writer);
2698
2698
2699
- buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack);
2699
+ let type = getTypeOfSymbol(p);
2700
+ if (isRequiredInitializedParameter(parameterNode)) {
2701
+ type = includeFalsyTypes(type, TypeFlags.Undefined);
2702
+ }
2703
+ buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
2700
2704
}
2701
2705
2702
2706
function buildBindingPatternDisplay(bindingPattern: BindingPattern, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
@@ -3277,6 +3281,16 @@ namespace ts {
3277
3281
return strictNullChecks && optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type;
3278
3282
}
3279
3283
3284
+ /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */
3285
+ function removeOptionalityFromAnnotation(annotatedType: Type, declaration: VariableLikeDeclaration): Type {
3286
+ const annotationIncludesUndefined = strictNullChecks &&
3287
+ declaration.kind === SyntaxKind.Parameter &&
3288
+ declaration.initializer &&
3289
+ getFalsyFlags(annotatedType) & TypeFlags.Undefined &&
3290
+ !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined);
3291
+ return annotationIncludesUndefined ? getNonNullableType(annotatedType) : annotatedType;
3292
+ }
3293
+
3280
3294
// Return the inferred type for a variable, parameter, or property declaration
3281
3295
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type {
3282
3296
if (declaration.flags & NodeFlags.JavaScriptFile) {
@@ -3310,7 +3324,8 @@ namespace ts {
3310
3324
3311
3325
// Use type from type annotation if one is present
3312
3326
if (declaration.type) {
3313
- return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
3327
+ const declaredType = removeOptionalityFromAnnotation(getTypeFromTypeNode(declaration.type), declaration);
3328
+ return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
3314
3329
}
3315
3330
3316
3331
if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
@@ -5204,6 +5219,12 @@ namespace ts {
5204
5219
Debug.assert(parameterIndex >= 0);
5205
5220
return parameterIndex >= signature.minArgumentCount;
5206
5221
}
5222
+ const iife = getImmediatelyInvokedFunctionExpression(node.parent);
5223
+ if (iife) {
5224
+ return !node.type &&
5225
+ !node.dotDotDotToken &&
5226
+ indexOf((node.parent as SignatureDeclaration).parameters, node) >= iife.arguments.length;
5227
+ }
5207
5228
5208
5229
return false;
5209
5230
}
@@ -7768,16 +7789,36 @@ namespace ts {
7768
7789
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
7769
7790
return Ternary.True;
7770
7791
}
7771
- const len = targetTypes.length;
7772
- for (let i = 0; i < len; i++) {
7773
- const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
7792
+ for (const type of targetTypes) {
7793
+ const related = isRelatedTo(source, type, /*reportErrors*/ false);
7774
7794
if (related) {
7775
7795
return related;
7776
7796
}
7777
7797
}
7798
+ if (reportErrors) {
7799
+ const discriminantType = findMatchingDiscriminantType(source, target);
7800
+ isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
7801
+ }
7778
7802
return Ternary.False;
7779
7803
}
7780
7804
7805
+ function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
7806
+ const sourceProperties = getPropertiesOfObjectType(source);
7807
+ if (sourceProperties) {
7808
+ for (const sourceProperty of sourceProperties) {
7809
+ if (isDiscriminantProperty(target, sourceProperty.name)) {
7810
+ const sourceType = getTypeOfSymbol(sourceProperty);
7811
+ for (const type of target.types) {
7812
+ const targetType = getTypeOfPropertyOfType(type, sourceProperty.name);
7813
+ if (targetType && isRelatedTo(sourceType, targetType)) {
7814
+ return type;
7815
+ }
7816
+ }
7817
+ }
7818
+ }
7819
+ }
7820
+ }
7821
+
7781
7822
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
7782
7823
let result = Ternary.True;
7783
7824
const targetTypes = target.types;
@@ -9881,7 +9922,19 @@ namespace ts {
9881
9922
}
9882
9923
}
9883
9924
let type: FlowType;
9884
- if (flow.flags & FlowFlags.Assignment) {
9925
+ if (flow.flags & FlowFlags.AfterFinally) {
9926
+ // block flow edge: finally -> pre-try (for larger explanation check comment in binder.ts - bindTryStatement
9927
+ (<AfterFinallyFlow>flow).locked = true;
9928
+ type = getTypeAtFlowNode((<AfterFinallyFlow>flow).antecedent);
9929
+ (<AfterFinallyFlow>flow).locked = false;
9930
+ }
9931
+ else if (flow.flags & FlowFlags.PreFinally) {
9932
+ // locked pre-finally flows are filtered out in getTypeAtFlowBranchLabel
9933
+ // so here just redirect to antecedent
9934
+ flow = (<PreFinallyFlow>flow).antecedent;
9935
+ continue;
9936
+ }
9937
+ else if (flow.flags & FlowFlags.Assignment) {
9885
9938
type = getTypeAtFlowAssignment(<FlowAssignment>flow);
9886
9939
if (!type) {
9887
9940
flow = (<FlowAssignment>flow).antecedent;
@@ -10037,6 +10090,12 @@ namespace ts {
10037
10090
let subtypeReduction = false;
10038
10091
let seenIncomplete = false;
10039
10092
for (const antecedent of flow.antecedents) {
10093
+ if (antecedent.flags & FlowFlags.PreFinally && (<PreFinallyFlow>antecedent).lock.locked) {
10094
+ // if flow correspond to branch from pre-try to finally and this branch is locked - this means that
10095
+ // we initially have started following the flow outside the finally block.
10096
+ // in this case we should ignore this branch.
10097
+ continue;
10098
+ }
10040
10099
const flowType = getTypeAtFlowNode(antecedent);
10041
10100
const type = getTypeFromFlowType(flowType);
10042
10101
// If the type at a particular antecedent path is the declared type and the
@@ -20708,6 +20767,13 @@ namespace ts {
20708
20767
return false;
20709
20768
}
20710
20769
20770
+ function isRequiredInitializedParameter(parameter: ParameterDeclaration) {
20771
+ return strictNullChecks &&
20772
+ !isOptionalParameter(parameter) &&
20773
+ parameter.initializer &&
20774
+ !(getModifierFlags(parameter) & ModifierFlags.ParameterPropertyModifier);
20775
+ }
20776
+
20711
20777
function getNodeCheckFlags(node: Node): NodeCheckFlags {
20712
20778
node = getParseTreeNode(node);
20713
20779
return node ? getNodeLinks(node).flags : undefined;
@@ -20799,10 +20865,12 @@ namespace ts {
20799
20865
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
20800
20866
// Get type of the symbol if this is the valid symbol otherwise get type at location
20801
20867
const symbol = getSymbolOfNode(declaration);
20802
- const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
20868
+ let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
20803
20869
? getWidenedLiteralType(getTypeOfSymbol(symbol))
20804
20870
: unknownType;
20805
-
20871
+ if (flags & TypeFormatFlags.AddUndefined) {
20872
+ type = includeFalsyTypes(type, TypeFlags.Undefined);
20873
+ }
20806
20874
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
20807
20875
}
20808
20876
@@ -20901,6 +20969,7 @@ namespace ts {
20901
20969
isTopLevelValueImportEqualsWithEntityName,
20902
20970
isDeclarationVisible,
20903
20971
isImplementationOfOverload,
20972
+ isRequiredInitializedParameter,
20904
20973
writeTypeOfDeclaration,
20905
20974
writeReturnTypeOfSignatureDeclaration,
20906
20975
writeTypeOfExpression,
0 commit comments