Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/ast/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ func IsClassElement(node *Node) bool {
return false
}

func isMethodOrAccessor(node *Node) bool {
func IsMethodOrAccessor(node *Node) bool {
switch node.Kind {
case KindMethodDeclaration, KindGetAccessor, KindSetAccessor:
return true
Expand All @@ -580,7 +580,7 @@ func isMethodOrAccessor(node *Node) bool {
}

func IsPrivateIdentifierClassElementDeclaration(node *Node) bool {
return (IsPropertyDeclaration(node) || isMethodOrAccessor(node)) && IsPrivateIdentifier(node.Name())
return (IsPropertyDeclaration(node) || IsMethodOrAccessor(node)) && IsPrivateIdentifier(node.Name())
}

func IsObjectLiteralOrClassExpressionMethodOrAccessor(node *Node) bool {
Expand Down
18 changes: 12 additions & 6 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -19101,11 +19101,9 @@ func (c *Checker) getSignaturesOfSymbol(symbol *ast.Symbol) []*Signature {
}
// If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters.
// Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would suppress checks that the two are compatible.
if ast.IsFunctionExpressionOrArrowFunction(decl) || ast.IsObjectLiteralMethod(decl) {
if sig := c.getSignatureOfFullSignatureType(decl); sig != nil {
result = append(result, sig)
continue
}
if sig := c.getSignatureOfFullSignatureType(decl); sig != nil {
result = append(result, sig)
continue
}
result = append(result, c.getSignatureFromDeclaration(decl))
}
Expand All @@ -19123,6 +19121,14 @@ func (c *Checker) getSignatureFromDeclaration(declaration *ast.Node) *Signature
minArgumentCount := 0
hasThisParameter := false
iife := ast.GetImmediatelyInvokedFunctionExpression(declaration)
isUntypedSignatureInJSFile := iife == nil &&
ast.IsInJSFile(declaration) &&
(ast.IsFunctionExpression(declaration) || ast.IsArrowFunction(declaration) || ast.IsMethodOrAccessor(declaration) || ast.IsFunctionDeclaration(declaration) || ast.IsConstructorDeclaration(declaration)) &&
core.Every(declaration.Parameters(), func(param *ast.Node) bool { return param.Type() == nil }) &&
c.getContextualType(declaration, ContextFlagsSignature) == nil
if isUntypedSignatureInJSFile {
flags |= SignatureFlagsIsUntypedSignatureInJSFile
}
for i, param := range declaration.Parameters() {
paramSymbol := param.Symbol()
typeNode := param.Type()
Expand Down Expand Up @@ -19343,7 +19349,7 @@ func (c *Checker) getReturnTypeFromAnnotation(declaration *ast.Node) *Type {
}

func (c *Checker) getSignatureOfFullSignatureType(node *ast.Node) *Signature {
if ast.IsInJSFile(node) && ast.IsFunctionLike(node) && node.FunctionLikeData().FullSignature != nil {
if ast.IsInJSFile(node) && (ast.IsFunctionDeclaration(node) || ast.IsMethodDeclaration(node) || ast.IsFunctionExpressionOrArrowFunction(node)) && node.FunctionLikeData().FullSignature != nil {
return c.getSingleCallSignature(c.getTypeFromTypeNode(node.FunctionLikeData().FullSignature))
}
return nil
Expand Down
21 changes: 14 additions & 7 deletions internal/checker/emitresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,20 @@ func (r *emitResolver) IsImplementationOfOverload(node *ast.SignatureDeclaration
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
return len(signaturesOfSymbol) > 1 ||
// If there is single signature for the symbol, it is overload if that signature isn't coming from the node
// e.g.: function foo(a: string): string;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
(len(signaturesOfSymbol) == 1 && signaturesOfSymbol[0].declaration != node)
if len(signaturesOfSymbol) > 1 {
return true
}
// If there is single signature for the symbol, it is overload if that signature isn't coming from the node
// e.g.: function foo(a: string): string;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
if len(signaturesOfSymbol) == 1 {
declaration := signaturesOfSymbol[0].declaration
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition declaration.Flags&ast.NodeFlagsJSDoc == 0 checks if the JSDoc flag is NOT set, but there's no comment explaining why JSDoc-flagged declarations should be excluded from being considered overload implementations. Adding a brief comment would clarify this non-obvious logic.

Suggested change
declaration := signaturesOfSymbol[0].declaration
declaration := signaturesOfSymbol[0].declaration
// JSDoc signatures are not considered overloads, so exclude JSDoc-flagged declarations.

Copilot uses AI. Check for mistakes.
if declaration != node && declaration.Flags&ast.NodeFlagsJSDoc == 0 {
return true
}
}
}
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @param {2} a
*/
export function conflictingParam(a) { return true }
>conflictingParam : (a: 2) => true
>conflictingParam : (a: 1) => true
>a : 2
>true : true

Expand All @@ -15,7 +15,7 @@ export function conflictingParam(a) { return true }
* @return {false}
*/
export function conflictingReturn(b) { return false }
>conflictingReturn : (b: 3) => false
>conflictingReturn : (b: 3) => true
>b : 3
>false : false

Expand All @@ -26,7 +26,7 @@ export function conflictingReturn(b) { return false }
* @return {false}
*/
export function conflictingBoth(d) { return false }
>conflictingBoth : (d: 5) => false
>conflictingBoth : (c: 4) => true
>d : 5
>false : false

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
main.js(3,9): error TS2554: Expected 0 arguments, but got 3.
main.js(5,1): error TS2554: Expected 2 arguments, but got 0.
main.js(6,16): error TS2554: Expected 2 arguments, but got 3.
main.js(6,16): error TS2554: Expected 0-2 arguments, but got 3.


==== main.js (3 errors) ====
==== main.js (2 errors) ====
function allRest() { arguments; }
allRest();
allRest(1, 2, 3);
~~~~~~~
!!! error TS2554: Expected 0 arguments, but got 3.
function someRest(x, y) { arguments; }
someRest(); // x and y are still optional because they are in a JS file
~~~~~~~~
!!! error TS2554: Expected 2 arguments, but got 0.
!!! related TS6210 main.js:4:19: An argument for 'x' was not provided.
someRest(1, 2, 3);
~
!!! error TS2554: Expected 2 arguments, but got 3.
!!! error TS2554: Expected 0-2 arguments, but got 3.

/**
* @param {number} x - a thing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
a.js(9,7): error TS2554: Expected 1 arguments, but got 3.
a.js(9,7): error TS2554: Expected 0-1 arguments, but got 3.


==== a.js (1 errors) ====
Expand All @@ -12,5 +12,5 @@ a.js(9,7): error TS2554: Expected 1 arguments, but got 3.

f2(1, 2, 3);
~~~~
!!! error TS2554: Expected 1 arguments, but got 3.
!!! error TS2554: Expected 0-1 arguments, but got 3.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
a.js(5,6): error TS2554: Expected 1 arguments, but got 3.
a.js(5,6): error TS2554: Expected 0-1 arguments, but got 3.


==== a.js (1 errors) ====
Expand All @@ -8,5 +8,5 @@ a.js(5,6): error TS2554: Expected 1 arguments, but got 3.

f(1, 2, 3);
~~~~
!!! error TS2554: Expected 1 arguments, but got 3.
!!! error TS2554: Expected 0-1 arguments, but got 3.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
index.js(1,25): error TS7006: Parameter 'f' implicitly has an 'any' type.
index.js(13,29): error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[f: any]'.
index.js(13,29): error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[f?: any]'.


==== index.js (2 errors) ====
Expand All @@ -19,6 +19,6 @@ index.js(13,29): error TS2345: Argument of type 'IArguments' is not assignable t
const debuglog = function() {
return format.apply(null, arguments);
~~~~~~~~~
!!! error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[f: any]'.
!!! error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[f?: any]'.
};

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var k = function (x) { return x }
/** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */
/** @type {Argle} */
function blargle(s) {
>blargle : (s: "bye" | "hi") => 0 | 1 | 2
>blargle : (x: "bye" | "hi") => 0 | 1 | 2
>s : "bye" | "hi"

return 0;
Expand All @@ -57,7 +57,7 @@ function blargle(s) {
var zeroonetwo = blargle('hi')
>zeroonetwo : 0 | 1 | 2
>blargle('hi') : 0 | 1 | 2
>blargle : (s: "bye" | "hi") => 0 | 1 | 2
>blargle : (x: "bye" | "hi") => 0 | 1 | 2
>'hi' : "hi"

/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var g = function (prop) {

/** @type {(a: number) => number} */
function add1(a, b) { return a + b; }
>add1 : (a: number, b: any) => number
>add1 : (a: number) => number
>a : number
>b : any
>a + b : any
Expand All @@ -37,7 +37,7 @@ function add2(a, b) { return a + b; }
// TODO: Should be an error since signature doesn't match.
/** @type {(a: number, b: number, c: number) => number} */
function add3(a, b) { return a + b; }
>add3 : (a: number, b: number) => number
>add3 : (a: number, b: number, c: number) => number
>a : number
>b : number
>a + b : number
Expand All @@ -49,7 +49,7 @@ function add3(a, b) { return a + b; }

/** @type {() => void} */
function funcWithMoreParameters(more) {} // error
>funcWithMoreParameters : (more: any) => void
>funcWithMoreParameters : () => void
>more : any

/** @type {() => void} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ class C {

/** @type {(optional?) => void} */
methodWithOptionalParameters() {}
>methodWithOptionalParameters : () => void
>methodWithOptionalParameters : (optional?: any) => void
}

Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
error TS5055: Cannot write file 'jsdocReadonlyDeclarations.js' because it would overwrite input file.
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
error TS5102: Option 'outFile' has been removed. Please remove it from your configuration.
jsdocReadonlyDeclarations.js(14,1): error TS2554: Expected 1 arguments, but got 0.


!!! error TS5055: Cannot write file 'jsdocReadonlyDeclarations.js' because it would overwrite input file.
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
!!! error TS5102: Option 'outFile' has been removed. Please remove it from your configuration.
==== jsdocReadonlyDeclarations.js (1 errors) ====
==== jsdocReadonlyDeclarations.js (0 errors) ====
class C {
/** @readonly */
x = 6
Expand All @@ -22,9 +21,6 @@ jsdocReadonlyDeclarations.js(14,1): error TS2554: Expected 1 arguments, but got
}
}
new C().x
~~~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! related TS6210 jsdocReadonlyDeclarations.js:5:17: An argument for 'n' was not provided.

function F() {
/** @readonly */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const f1 = function() {

/** @type {import('./types').M} */
export function f2() {
>f2 : () => void
>f2 : (this: import("/types").Foo) => void

this.test();
>this.test() : any
Expand All @@ -48,7 +48,7 @@ export const f3 = function() {

/** @type {(this: import('./types').Foo) => void} */
export function f4() {
>f4 : () => void
>f4 : (this: import("/types").Foo) => void

this.test();
>this.test() : any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ a.js(13,1): error TS2554: Expected 1 arguments, but got 0.
g() // should error
~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! related TS6210 a.js:5:12: An argument for 's' was not provided.
!!! related TS6210 a.js:4:13: An argument for 's' was not provided.
h()
~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! related TS6210 a.js:8:12: An argument for 's' was not provided.
!!! related TS6210 a.js:7:14: An argument for 's' was not provided.

This file was deleted.

Loading