From a235d544f3213bde39fda163a65c6147967b3a67 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 30 Jan 2017 14:59:23 -0800 Subject: [PATCH] Remove undefined from initialized+annotated parameter type --- src/compiler/checker.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a9c98d02341..199cb60c3c7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3286,6 +3286,16 @@ namespace ts { return strictNullChecks && optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type; } + /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ + function removeOptionalityFromAnnotation(annotatedType: Type, declaration: VariableLikeDeclaration): Type { + const annotationIncludesUndefined = strictNullChecks && + declaration.kind === SyntaxKind.Parameter && + declaration.initializer && + getFalsyFlags(annotatedType) & TypeFlags.Undefined && + !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); + return annotationIncludesUndefined ? getNonNullableType(annotatedType) : annotatedType; + } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type { if (declaration.flags & NodeFlags.JavaScriptFile) { @@ -3319,7 +3329,8 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { - return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality); + const declaredType = removeOptionalityFromAnnotation(getTypeFromTypeNode(declaration.type), declaration); + return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality); } if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&