Skip to content
Draft
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
3 changes: 3 additions & 0 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24325,6 +24325,9 @@ func (c *Checker) getConditionalFlowTypeOfType(t *Type, node *ast.Node) *Type {
covariant := true
for node != nil && !ast.IsStatement(node) && node.Kind != ast.KindJSDoc {
parent := node.Parent
if parent == nil {
break
}
// only consider variance flipped by parameter locations - `keyof` types would usually be considered variance inverting, but
// often get used in indexed accesses where they behave sortof invariantly, but our checking is lax
if ast.IsParameter(parent) {
Expand Down
4 changes: 4 additions & 0 deletions internal/diagnostics/diagnostics_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/diagnostics/extraDiagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,9 @@
"Option '--incremental' is only valid with a known configuration file (like 'tsconfig.json') or when '--tsBuildInfoFile' is explicitly provided.": {
"category": "Error",
"code": 5074
},
"A JSDoc '@overload' tag is not allowed in this context.": {
"category": "Error",
"code": 8110
}
}
16 changes: 15 additions & 1 deletion internal/parser/reparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package parser
import (
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/diagnostics"
)

func (p *Parser) finishReparsedNode(node *ast.Node, locationNode *ast.Node) {
Expand Down Expand Up @@ -112,7 +113,20 @@ func (p *Parser) reparseUnhosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Nod
p.reparseList = append(p.reparseList, importDeclaration)
case ast.KindJSDocOverloadTag:
if fun, ok := getFunctionLikeHost(parent); ok {
p.reparseList = append(p.reparseList, p.reparseJSDocSignature(tag.AsJSDocOverloadTag().TypeExpression, fun, jsDoc, tag, fun.Modifiers()))
// Only allow @overload on function declarations and class/interface method declarations.
// Disallow on object literal methods by checking if we're in the ObjectLiteralMembers parsing context.
isObjectLiteralMethod := parent.Kind == ast.KindMethodDeclaration &&
p.parsingContexts&(1<<PCObjectLiteralMembers) != 0

if !isObjectLiteralMethod &&
(parent.Kind == ast.KindFunctionDeclaration ||
parent.Kind == ast.KindMethodDeclaration ||
parent.Kind == ast.KindMethodSignature) {
p.reparseList = append(p.reparseList, p.reparseJSDocSignature(tag.AsJSDocOverloadTag().TypeExpression, fun, jsDoc, tag, fun.Modifiers()))
} else {
// Report error for @overload on object literal methods
p.parseErrorAtRange(tag.TagName().Loc, diagnostics.A_JSDoc_overload_tag_is_not_allowed_in_this_context)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
test.js(20,15): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.


==== test.js (1 errors) ====
const foo = {
/**
* @overload
* @param {string} termCode
* @param {string[]} crnList
* @param {string} sis
* @returns {Record<string, string>}
*/
/**
* @overload
* @param {string} termCode
* @param {string} crn
* @param {string} sis
* @returns {string}
*/
/**
* @param {string} termCode
* @param {string | string[]} crnList
* @param {string} sis
* @returns {string | Record<string, string>}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.
*/
getStatus(termCode, crnList, sis) {},
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//// [tests/cases/compiler/nilPointerInConditionalFlowType.ts] ////

//// [test.js]
const foo = {
/**
* @overload
* @param {string} termCode
* @param {string[]} crnList
* @param {string} sis
* @returns {Record<string, string>}
*/
/**
* @overload
* @param {string} termCode
* @param {string} crn
* @param {string} sis
* @returns {string}
*/
/**
* @param {string} termCode
* @param {string | string[]} crnList
* @param {string} sis
* @returns {string | Record<string, string>}
*/
getStatus(termCode, crnList, sis) {},
};


//// [test.js]
const foo = {
/**
* @overload
* @param {string} termCode
* @param {string[]} crnList
* @param {string} sis
* @returns {Record<string, string>}
*/
/**
* @overload
* @param {string} termCode
* @param {string} crn
* @param {string} sis
* @returns {string}
*/
/**
* @param {string} termCode
* @param {string | string[]} crnList
* @param {string} sis
* @returns {string | Record<string, string>}
*/
getStatus(termCode, crnList, sis) { },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//// [tests/cases/compiler/nilPointerInConditionalFlowType.ts] ////

=== test.js ===
const foo = {
>foo : Symbol(foo, Decl(test.js, 0, 5))

/**
* @overload
* @param {string} termCode
* @param {string[]} crnList
* @param {string} sis
* @returns {Record<string, string>}
*/
/**
* @overload
* @param {string} termCode
* @param {string} crn
* @param {string} sis
* @returns {string}
*/
/**
* @param {string} termCode
* @param {string | string[]} crnList
* @param {string} sis
* @returns {string | Record<string, string>}
*/
getStatus(termCode, crnList, sis) {},
>getStatus : Symbol(getStatus, Decl(test.js, 0, 13))
>termCode : Symbol(termCode, Decl(test.js, 21, 11))
>crnList : Symbol(crnList, Decl(test.js, 21, 20))
>sis : Symbol(sis, Decl(test.js, 21, 29))

};

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//// [tests/cases/compiler/nilPointerInConditionalFlowType.ts] ////

=== test.js ===
const foo = {
>foo : { getStatus(termCode: string, crnList: string | string[], sis: string): string | Record<string, string>; }
>{ /** * @overload * @param {string} termCode * @param {string[]} crnList * @param {string} sis * @returns {Record<string, string>} */ /** * @overload * @param {string} termCode * @param {string} crn * @param {string} sis * @returns {string} */ /** * @param {string} termCode * @param {string | string[]} crnList * @param {string} sis * @returns {string | Record<string, string>} */ getStatus(termCode, crnList, sis) {},} : { getStatus(termCode: string, crnList: string | string[], sis: string): string | Record<string, string>; }

/**
* @overload
* @param {string} termCode
* @param {string[]} crnList
* @param {string} sis
* @returns {Record<string, string>}
*/
/**
* @overload
* @param {string} termCode
* @param {string} crn
* @param {string} sis
* @returns {string}
*/
/**
* @param {string} termCode
* @param {string | string[]} crnList
* @param {string} sis
* @returns {string | Record<string, string>}
*/
getStatus(termCode, crnList, sis) {},
>getStatus : (termCode: string, crnList: string | string[], sis: string) => string | Record<string, string>
>termCode : string
>crnList : string | string[]
>sis : string

};

Original file line number Diff line number Diff line change
Expand Up @@ -131,27 +131,6 @@ export declare class Processor<ParseTree extends Node | undefined = undefined, H
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(preset?: string | null | undefined): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use<Parameters extends Array<unknown> = [], Input extends Node | string | undefined = undefined, Output = Input>(plugin: number, ...parameters: (Parameters | [boolean])): Processor;
use(value: string | number | boolean | null | undefined, ...parameters: unknown[]): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
}
export {};
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Processor {
* Current processor.
*/
use(value, ...parameters) {
>use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>value : Symbol(value, Decl(typeTagForMultipleVariableDeclarations.js, 35, 6))
>parameters : Symbol(parameters, Decl(typeTagForMultipleVariableDeclarations.js, 35, 12))

Expand All @@ -59,9 +59,9 @@ var x = 1, y = 2, z = 3;
>z : Symbol(z, Decl(typeTagForMultipleVariableDeclarations.js, 40, 17))

p.use(x, y, z);
>p.use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>p.use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>p : Symbol(p, Decl(typeTagForMultipleVariableDeclarations.js, 39, 3))
>use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>use : Symbol(Processor.use, Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>x : Symbol(x, Decl(typeTagForMultipleVariableDeclarations.js, 40, 3))
>y : Symbol(y, Decl(typeTagForMultipleVariableDeclarations.js, 40, 10))
>z : Symbol(z, Decl(typeTagForMultipleVariableDeclarations.js, 40, 17))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Processor {
* Current processor.
*/
use(value, ...parameters) {
>use : { (preset?: string): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>use : (value: string | number | boolean, ...parameters: unknown[]) => Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>
>value : string | number | boolean
>parameters : unknown[]

Expand All @@ -64,9 +64,9 @@ var x = 1, y = 2, z = 3;

p.use(x, y, z);
>p.use(x, y, z) : Processor<undefined, undefined, undefined, undefined, undefined>
>p.use : { (preset?: string): Processor<undefined, undefined, undefined, undefined, undefined>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>p.use : (value: string | number | boolean, ...parameters: unknown[]) => Processor<undefined, undefined, undefined, undefined, undefined>
>p : Processor<undefined, undefined, undefined, undefined, undefined>
>use : { (preset?: string): Processor<undefined, undefined, undefined, undefined, undefined>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>use : (value: string | number | boolean, ...parameters: unknown[]) => Processor<undefined, undefined, undefined, undefined, undefined>
>x : number
>y : number
>z : number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ const example3 = {


//// [jsFileAlternativeUseOfOverloadTag.d.ts]
declare function Example1(value: any): any;
declare const example1: {
/**
* @overload Example1(value)
Expand All @@ -115,8 +114,6 @@ declare const example1: {
*/
constructor: (value: any, options: any) => void;
};
declare function Example2(value: any, secretAccessKey: any, sessionToken: any): any;
declare function Example2(): any;
declare const example2: {
/**
* Example 2
Expand All @@ -138,7 +135,6 @@ declare const example2: {
*/
constructor: () => void;
};
declare function evaluate(): any;
type callback = (error: any, result: any) => any;
declare const example3: {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

//// [jsFileAlternativeUseOfOverloadTag.d.ts]
-declare namespace example1 {
+declare function Example1(value: any): any;
+declare const example1: {
/**
* @overload Example1(value)
Expand Down Expand Up @@ -58,8 +57,6 @@
-declare namespace example3 {
+ constructor: (value: any, options: any) => void;
+};
+declare function Example2(value: any, secretAccessKey: any, sessionToken: any): any;
+declare function Example2(): any;
+declare const example2: {
+ /**
+ * Example 2
Expand All @@ -81,13 +78,12 @@
+ */
+ constructor: () => void;
+};
+declare function evaluate(): any;
+type callback = (error: any, result: any) => any;
+declare const example3: {
/**
* @overload evaluate(options = {}, [callback])
* Evaluate something
@@= skipped -63, +48 lines =@@
@@= skipped -63, +44 lines =@@
* @param result [String]
* @see callback
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
overloadTag2.js(14,9): error TS2394: This overload signature is not compatible with its implementation signature.
overloadTag2.js(25,20): error TS7006: Parameter 'b' implicitly has an 'any' type.
overloadTag2.js(30,9): error TS2554: Expected 1-2 arguments, but got 0.
overloadTag2.js(30,9): error TS2554: Expected 2 arguments, but got 0.
overloadTag2.js(31,9): error TS2554: Expected 2 arguments, but got 1.
overloadTag2.js(32,9): error TS2554: Expected 2 arguments, but got 1.


==== overloadTag2.js (3 errors) ====
==== overloadTag2.js (4 errors) ====
export class Foo {
#a = true ? 1 : "1"
#b
Expand All @@ -18,9 +19,6 @@ overloadTag2.js(30,9): error TS2554: Expected 1-2 arguments, but got 0.
/**
* @constructor
* @overload
~~~~~~~~
!!! error TS2394: This overload signature is not compatible with its implementation signature.
!!! related TS2750 overloadTag2.js:25:5: The implementation signature is declared here.
* @param {number} a
*/
/**
Expand All @@ -40,9 +38,15 @@ overloadTag2.js(30,9): error TS2554: Expected 1-2 arguments, but got 0.
}
var a = new Foo()
~~~~~~~~~
!!! error TS2554: Expected 1-2 arguments, but got 0.
!!! related TS6210 overloadTag2.js:15:8: An argument for 'a' was not provided.
!!! error TS2554: Expected 2 arguments, but got 0.
!!! related TS6210 overloadTag2.js:25:17: An argument for 'a' was not provided.
var b = new Foo('str')
~~~~~~~~~~~~~~
!!! error TS2554: Expected 2 arguments, but got 1.
!!! related TS6210 overloadTag2.js:25:20: An argument for 'b' was not provided.
var c = new Foo(2)
~~~~~~~~~~
!!! error TS2554: Expected 2 arguments, but got 1.
!!! related TS6210 overloadTag2.js:25:20: An argument for 'b' was not provided.
var d = new Foo('str', 2)

Loading