mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 01:33:15 -05:00
Handle JS synthetic rest args in contextual parameter assignment (#48263)
* Handle JS synthetic rest args in contextual parameter assignment * Limit fixing to only unannotated js rest parameters * Minimize test * Add annotated version * Remove explicit CheckFlags.RestParameter check since apparently not all rest parameters are CheckFlags.RestParameter
This commit is contained in:
@@ -12862,7 +12862,19 @@ namespace ts {
|
||||
p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined);
|
||||
|
||||
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String, CheckFlags.RestParameter);
|
||||
syntheticArgsSymbol.type = lastParamVariadicType ? createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)) : anyArrayType;
|
||||
if (lastParamVariadicType) {
|
||||
// Parameter has effective annotation, lock in type
|
||||
syntheticArgsSymbol.type = createArrayType(getTypeFromTypeNode(lastParamVariadicType.type));
|
||||
}
|
||||
else {
|
||||
// Parameter has no annotation
|
||||
// By using a `DeferredType` symbol, we allow the type of this rest arg to be overriden by contextual type assignment so long as its type hasn't been
|
||||
// cached by `getTypeOfSymbol` yet.
|
||||
syntheticArgsSymbol.checkFlags |= CheckFlags.DeferredType;
|
||||
syntheticArgsSymbol.deferralParent = neverType;
|
||||
syntheticArgsSymbol.deferralConstituents = [anyArrayType];
|
||||
syntheticArgsSymbol.deferralWriteConstituents = [anyArrayType];
|
||||
}
|
||||
if (lastParamVariadicType) {
|
||||
// Replace the last parameter with a rest parameter.
|
||||
parameters.pop();
|
||||
@@ -32163,7 +32175,12 @@ namespace ts {
|
||||
if (signatureHasRestParameter(signature)) {
|
||||
// parameter might be a transient symbol generated by use of `arguments` in the function body.
|
||||
const parameter = last(signature.parameters);
|
||||
if (isTransientSymbol(parameter) || !getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)) {
|
||||
if (parameter.valueDeclaration
|
||||
? !getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)
|
||||
// a declarationless parameter may still have a `.type` already set by its construction logic
|
||||
// (which may pull a type from a jsdoc) - only allow fixing on `DeferredType` parameters with a fallback type
|
||||
: !!(getCheckFlags(parameter) & CheckFlags.DeferredType)
|
||||
) {
|
||||
const contextualParameterType = getRestTypeAtPosition(context, len);
|
||||
assignParameterType(parameter, contextualParameterType);
|
||||
}
|
||||
@@ -32182,9 +32199,9 @@ namespace ts {
|
||||
function assignParameterType(parameter: Symbol, type?: Type) {
|
||||
const links = getSymbolLinks(parameter);
|
||||
if (!links.type) {
|
||||
const declaration = parameter.valueDeclaration as ParameterDeclaration;
|
||||
links.type = type || getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true);
|
||||
if (declaration.name.kind !== SyntaxKind.Identifier) {
|
||||
const declaration = parameter.valueDeclaration as ParameterDeclaration | undefined;
|
||||
links.type = type || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter));
|
||||
if (declaration && declaration.name.kind !== SyntaxKind.Identifier) {
|
||||
// if inference didn't come up with anything but unknown, fall back to the binding pattern if present.
|
||||
if (links.type === unknownType) {
|
||||
links.type = getTypeFromBindingPattern(declaration.name);
|
||||
|
||||
Reference in New Issue
Block a user