mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Preserve parameter types for optional parameters /fields with undefined in type and for required params with default value (#57484)
This commit is contained in:
+10
-2
@@ -48132,6 +48132,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function declaredParameterTypeContainsUndefined(parameter: ParameterDeclaration) {
|
||||
if (!parameter.type) return false;
|
||||
const type = getTypeFromTypeNode(parameter.type);
|
||||
return containsUndefinedType(type);
|
||||
}
|
||||
function requiresAddingImplicitUndefined(parameter: ParameterDeclaration) {
|
||||
return (isRequiredInitializedParameter(parameter) || isOptionalUninitializedParameterProperty(parameter)) && !declaredParameterTypeContainsUndefined(parameter);
|
||||
}
|
||||
|
||||
function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean {
|
||||
return !!strictNullChecks &&
|
||||
!isOptionalParameter(parameter) &&
|
||||
@@ -48525,8 +48534,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
isTopLevelValueImportEqualsWithEntityName,
|
||||
isDeclarationVisible,
|
||||
isImplementationOfOverload,
|
||||
isRequiredInitializedParameter,
|
||||
isOptionalUninitializedParameterProperty,
|
||||
requiresAddingImplicitUndefined,
|
||||
isExpandoFunctionDeclaration,
|
||||
getPropertiesOfContainerFunction,
|
||||
createTypeOfDeclaration,
|
||||
|
||||
@@ -1091,8 +1091,7 @@ export const notImplementedResolver: EmitResolver = {
|
||||
isLateBound: (_node): _node is LateBoundDeclaration => false,
|
||||
collectLinkedAliases: notImplemented,
|
||||
isImplementationOfOverload: notImplemented,
|
||||
isRequiredInitializedParameter: notImplemented,
|
||||
isOptionalUninitializedParameterProperty: notImplemented,
|
||||
requiresAddingImplicitUndefined: notImplemented,
|
||||
isExpandoFunctionDeclaration: notImplemented,
|
||||
getPropertiesOfContainerFunction: notImplemented,
|
||||
createTypeOfDeclaration: notImplemented,
|
||||
|
||||
@@ -127,7 +127,6 @@ import {
|
||||
isModuleDeclaration,
|
||||
isOmittedExpression,
|
||||
isPrivateIdentifier,
|
||||
isPropertySignature,
|
||||
isSemicolonClassElement,
|
||||
isSetAccessorDeclaration,
|
||||
isSourceFile,
|
||||
@@ -708,7 +707,6 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
| FunctionDeclaration
|
||||
| MethodDeclaration
|
||||
| GetAccessorDeclaration
|
||||
| SetAccessorDeclaration
|
||||
| BindingElement
|
||||
| ConstructSignatureDeclaration
|
||||
| VariableDeclaration
|
||||
@@ -727,46 +725,43 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
// Literal const declarations will have an initializer ensured rather than a type
|
||||
return;
|
||||
}
|
||||
const shouldUseResolverType = node.kind === SyntaxKind.Parameter &&
|
||||
(resolver.isRequiredInitializedParameter(node) ||
|
||||
resolver.isOptionalUninitializedParameterProperty(node));
|
||||
if (type && !shouldUseResolverType) {
|
||||
const shouldAddImplicitUndefined = node.kind === SyntaxKind.Parameter && resolver.requiresAddingImplicitUndefined(node);
|
||||
if (type && !shouldAddImplicitUndefined) {
|
||||
return visitNode(type, visitDeclarationSubtree, isTypeNode);
|
||||
}
|
||||
if (!getParseTreeNode(node)) {
|
||||
return type ? visitNode(type, visitDeclarationSubtree, isTypeNode) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
}
|
||||
if (node.kind === SyntaxKind.SetAccessor) {
|
||||
// Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now
|
||||
// (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that)
|
||||
return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
}
|
||||
|
||||
errorNameNode = node.name;
|
||||
let oldDiag: typeof getSymbolAccessibilityDiagnostic;
|
||||
if (!suppressNewDiagnosticContexts) {
|
||||
oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node);
|
||||
}
|
||||
if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
|
||||
return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
|
||||
let typeNode;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldAddImplicitUndefined);
|
||||
break;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.CallSignature:
|
||||
typeNode = resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(node);
|
||||
}
|
||||
if (
|
||||
node.kind === SyntaxKind.Parameter
|
||||
|| node.kind === SyntaxKind.PropertyDeclaration
|
||||
|| node.kind === SyntaxKind.PropertySignature
|
||||
) {
|
||||
if (isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType));
|
||||
return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
|
||||
}
|
||||
return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
|
||||
|
||||
function cleanup(returnValue: TypeNode | undefined) {
|
||||
errorNameNode = undefined;
|
||||
if (!suppressNewDiagnosticContexts) {
|
||||
getSymbolAccessibilityDiagnostic = oldDiag;
|
||||
}
|
||||
return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
errorNameNode = undefined;
|
||||
if (!suppressNewDiagnosticContexts) {
|
||||
getSymbolAccessibilityDiagnostic = oldDiag!;
|
||||
}
|
||||
return typeNode ?? factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
}
|
||||
|
||||
function isDeclarationAndNotVisible(node: NamedDeclaration) {
|
||||
|
||||
@@ -5603,8 +5603,7 @@ export interface EmitResolver {
|
||||
isLateBound(node: Declaration): node is LateBoundDeclaration;
|
||||
collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined;
|
||||
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
|
||||
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
|
||||
isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean;
|
||||
requiresAddingImplicitUndefined(node: ParameterDeclaration): boolean;
|
||||
isExpandoFunctionDeclaration(node: FunctionDeclaration): boolean;
|
||||
getPropertiesOfContainerFunction(node: Declaration): Symbol[];
|
||||
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression | ElementAccessExpression | BinaryExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined;
|
||||
|
||||
Reference in New Issue
Block a user