Remove undefined from the type of default initialised parameters when narrowing#14498
Merged
Remove undefined from the type of default initialised parameters when narrowing#14498
Conversation
When narrowing, remove optionality from the initial type of parameters with initialisers. Note that the type of the initialiser is not used; its presence just means that the initial type of the parameter can't contain undefined. It could contain any other member of a declared union type.
Member
Author
|
@ahejlsberg can you take a look? |
|
That is, it's treated as a narrowing instead of removing |
ahejlsberg
requested changes
Mar 7, 2017
src/compiler/checker.ts
Outdated
| declaration.initializer && | ||
| getFalsyFlags(declaredType) & TypeFlags.Undefined && | ||
| !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); | ||
| return annotationIncludesUndefined ? getNonNullableType(declaredType) : declaredType; |
Member
There was a problem hiding this comment.
This line is the source if the issue with null I mentioned. It removes both undefined and null. You need to use getTypeWithFacts(declaredType, TypeFacts.NEUndefined) instead.
src/compiler/checker.ts
Outdated
| const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : | ||
| type === autoType || type === autoArrayType ? undefinedType : | ||
| includeFalsyTypes(type, TypeFlags.Undefined); | ||
| const flowType = isFlowNarrowable(node, type, !assumeInitialized) ? getFlowTypeOfReference(node, type, initialType, flowContainer) : type; |
Member
There was a problem hiding this comment.
I would keep the isFlowNarrowable logic inside getFlowTypeOfReference, even if it means adding another parameter. Otherwise, you have to always write this combined pattern which is even more complicated.
ahejlsberg
reviewed
Mar 7, 2017
src/compiler/checker.ts
Outdated
| function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) { | ||
| let key: string; | ||
| if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) { | ||
| if (!isFlowNarrowable(reference, declaredType, couldBeUninitialized)) { |
Member
There was a problem hiding this comment.
Just inline the function here. It's not called anywhere else best I can tell.
ahejlsberg
approved these changes
Mar 7, 2017
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When narrowing, remove optionality from the initial type of parameters with initialisers. Note that the type of the initialiser is not used; its presence just means that the initial type of the parameter
can't contain undefined. It could contain any other member of a declared union type.
This fix builds on the previous fix #12033, but is slightly more complex in that it changes the initial type before control flow analysis rather than just throwing undefined away from the declared type.
The code refactors most of the complexity into
checkIdentifier, out ofgetFlowTypeOfReference, since it's only needed there. Suggestions on simplifying the mess of conditionals are welcome!Fixes #14487
Fixes #14425
Fixes #14236