Better error message for unparenthesized function/constructor type notation in union/intersection types (#39570)

* add graceful error message for unparenthesized function types in union and intersection

* add unparenthesizedFunctionTypeInUnionOrIntersection test

* add unparenthesizedConstructorTypeInUnionOrIntersection test

* Update src/compiler/parser.ts

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>

* pass isInUnionType to parseFunctionOrConstructorTypeToError

* Apply suggestions from code review

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>

* syntax fix

* refactor isStartOfFunctionType into isStartOfFunctionTypeOrConstructorType

* Update src/compiler/parser.ts

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>

* hoist isUnionType

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
uhyo 2020-07-16 06:43:56 +09:00 committed by GitHub
parent 37e6e2761c
commit b6f09ccf06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 616 additions and 5 deletions

View File

@ -1164,6 +1164,22 @@
"category": "Error",
"code": 1384
},
"Function type notation must be parenthesized when used in a union type.": {
"category": "Error",
"code": 1385
},
"Constructor type notation must be parenthesized when used in a union type.": {
"category": "Error",
"code": 1386
},
"Function type notation must be parenthesized when used in an intersection type.": {
"category": "Error",
"code": 1387
},
"Constructor type notation must be parenthesized when used in an intersection type.": {
"category": "Error",
"code": 1388
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",

View File

@ -3569,18 +3569,46 @@ namespace ts {
return parsePostfixTypeOrHigher();
}
function parseFunctionOrConstructorTypeToError(
isInUnionType: boolean
): TypeNode | undefined {
// the function type and constructor type shorthand notation
// are not allowed directly in unions and intersections, but we'll
// try to parse them gracefully and issue a helpful message.
if (isStartOfFunctionTypeOrConstructorType()) {
const type = parseFunctionOrConstructorType();
let diagnostic: DiagnosticMessage;
if (isFunctionTypeNode(type)) {
diagnostic = isInUnionType
? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type
: Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
}
else {
diagnostic = isInUnionType
? Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type
: Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
}
parseErrorAtRange(type, diagnostic);
return type;
}
return undefined;
}
function parseUnionOrIntersectionType(
operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken,
parseConstituentType: () => TypeNode,
createTypeNode: (types: NodeArray<TypeNode>) => UnionOrIntersectionTypeNode
): TypeNode {
const pos = getNodePos();
const isUnionType = operator === SyntaxKind.BarToken;
const hasLeadingOperator = parseOptional(operator);
let type = parseConstituentType();
let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType)
|| parseConstituentType();
if (token() === operator || hasLeadingOperator) {
const types = [type];
while (parseOptional(operator)) {
types.push(parseConstituentType());
types.push(parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType());
}
type = finishNode(createTypeNode(createNodeArray(types, pos)), pos);
}
@ -3595,11 +3623,14 @@ namespace ts {
return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode);
}
function isStartOfFunctionType(): boolean {
function isStartOfFunctionTypeOrConstructorType(): boolean {
if (token() === SyntaxKind.LessThanToken) {
return true;
}
return token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType);
if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) {
return true;
}
return token() === SyntaxKind.NewKeyword;
}
function skipParameterStart(): boolean {
@ -3684,7 +3715,7 @@ namespace ts {
}
function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
if (isStartOfFunctionType() || token() === SyntaxKind.NewKeyword) {
if (isStartOfFunctionTypeOrConstructorType()) {
return parseFunctionOrConstructorType();
}
const pos = getNodePos();

View File

@ -0,0 +1,78 @@
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(1,19): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(2,19): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(3,12): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(4,12): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(5,19): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(8,4): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(11,19): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(12,19): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(13,12): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(14,12): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(15,19): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(18,4): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(20,37): error TS1386: Constructor type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(21,31): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(22,16): error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts(22,41): error TS1386: Constructor type notation must be parenthesized when used in a union type.
==== tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts (16 errors) ====
type U1 = string | new () => void;
~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type U2 = string | new (foo: number) => void
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type U3 = | new () => number
~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type U4 = | new (foo?: number) => void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type U5 = string | new (number: number, foo?: string) => void | number;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type U6 =
| string
| new (...args: any[]) => void
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| number;
~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type I1 = string & new () => void;
~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type I2 = string & new (...foo: number[]) => void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type I3 = & new () => boolean
~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type I4 = & new () => boolean & null;
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type I5 = string & new (any: any, any2: any) => any & any;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type I6 =
& string
& new (foo: any) => void;
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type M1 = string | number & string | new () => number;
~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type M2 = any & string | any & new () => void;
~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
type M3 = any & new (foo: any) => void | new () => void & any;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1388: Constructor type notation must be parenthesized when used in an intersection type.
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1386: Constructor type notation must be parenthesized when used in a union type.
type OK1 = string | (new ()=> void);
type OK2 = string | (new ()=> string | number);

View File

@ -0,0 +1,29 @@
//// [unparenthesizedConstructorTypeInUnionOrIntersection.ts]
type U1 = string | new () => void;
type U2 = string | new (foo: number) => void
type U3 = | new () => number
type U4 = | new (foo?: number) => void;
type U5 = string | new (number: number, foo?: string) => void | number;
type U6 =
| string
| new (...args: any[]) => void
| number;
type I1 = string & new () => void;
type I2 = string & new (...foo: number[]) => void;
type I3 = & new () => boolean
type I4 = & new () => boolean & null;
type I5 = string & new (any: any, any2: any) => any & any;
type I6 =
& string
& new (foo: any) => void;
type M1 = string | number & string | new () => number;
type M2 = any & string | any & new () => void;
type M3 = any & new (foo: any) => void | new () => void & any;
type OK1 = string | (new ()=> void);
type OK2 = string | (new ()=> string | number);
//// [unparenthesizedConstructorTypeInUnionOrIntersection.js]

View File

@ -0,0 +1,70 @@
=== tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts ===
type U1 = string | new () => void;
>U1 : Symbol(U1, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 0, 0))
type U2 = string | new (foo: number) => void
>U2 : Symbol(U2, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 0, 34))
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 1, 24))
type U3 = | new () => number
>U3 : Symbol(U3, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 1, 44))
type U4 = | new (foo?: number) => void;
>U4 : Symbol(U4, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 2, 28))
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 3, 17))
type U5 = string | new (number: number, foo?: string) => void | number;
>U5 : Symbol(U5, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 3, 39))
>number : Symbol(number, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 4, 24))
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 4, 39))
type U6 =
>U6 : Symbol(U6, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 4, 71))
| string
| new (...args: any[]) => void
>args : Symbol(args, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 7, 9))
| number;
type I1 = string & new () => void;
>I1 : Symbol(I1, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 8, 11))
type I2 = string & new (...foo: number[]) => void;
>I2 : Symbol(I2, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 10, 34))
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 11, 24))
type I3 = & new () => boolean
>I3 : Symbol(I3, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 11, 50))
type I4 = & new () => boolean & null;
>I4 : Symbol(I4, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 12, 29))
type I5 = string & new (any: any, any2: any) => any & any;
>I5 : Symbol(I5, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 13, 37))
>any : Symbol(any, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 14, 24))
>any2 : Symbol(any2, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 14, 33))
type I6 =
>I6 : Symbol(I6, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 14, 58))
& string
& new (foo: any) => void;
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 17, 9))
type M1 = string | number & string | new () => number;
>M1 : Symbol(M1, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 17, 27))
type M2 = any & string | any & new () => void;
>M2 : Symbol(M2, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 19, 54))
type M3 = any & new (foo: any) => void | new () => void & any;
>M3 : Symbol(M3, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 20, 46))
>foo : Symbol(foo, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 21, 21))
type OK1 = string | (new ()=> void);
>OK1 : Symbol(OK1, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 21, 62))
type OK2 = string | (new ()=> string | number);
>OK2 : Symbol(OK2, Decl(unparenthesizedConstructorTypeInUnionOrIntersection.ts, 23, 36))

View File

@ -0,0 +1,71 @@
=== tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts ===
type U1 = string | new () => void;
>U1 : U1
type U2 = string | new (foo: number) => void
>U2 : U2
>foo : number
type U3 = | new () => number
>U3 : new () => number
type U4 = | new (foo?: number) => void;
>U4 : new (foo?: number) => void
>foo : number
type U5 = string | new (number: number, foo?: string) => void | number;
>U5 : U5
>number : number
>foo : string
type U6 =
>U6 : U6
| string
| new (...args: any[]) => void
>args : any[]
| number;
type I1 = string & new () => void;
>I1 : I1
type I2 = string & new (...foo: number[]) => void;
>I2 : I2
>foo : number[]
type I3 = & new () => boolean
>I3 : new () => boolean
type I4 = & new () => boolean & null;
>I4 : new () => boolean & null
>null : null
type I5 = string & new (any: any, any2: any) => any & any;
>I5 : I5
>any : any
>any2 : any
type I6 =
>I6 : I6
& string
& new (foo: any) => void;
>foo : any
type M1 = string | number & string | new () => number;
>M1 : M1
type M2 = any & string | any & new () => void;
>M2 : any
type M3 = any & new (foo: any) => void | new () => void & any;
>M3 : any
>foo : any
type OK1 = string | (new ()=> void);
>OK1 : OK1
type OK2 = string | (new ()=> string | number);
>OK2 : OK2

View File

@ -0,0 +1,80 @@
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(1,19): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(2,19): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(3,12): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(4,12): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(5,19): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(8,4): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(11,19): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(12,19): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(13,12): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(14,12): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(15,19): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(18,4): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(20,37): error TS1385: Function type notation must be parenthesized when used in a union type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(21,31): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(22,16): error TS1387: Function type notation must be parenthesized when used in an intersection type.
tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts(22,37): error TS1385: Function type notation must be parenthesized when used in a union type.
==== tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts (16 errors) ====
type U1 = string | () => void;
~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type U2 = string | (foo: number) => void
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type U3 = | () => number
~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type U4 = | (foo?: number) => void;
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type U5 = string | (number: number, foo?: string) => void | number;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type U6 =
| string
| (...args: any[]) => void
~~~~~~~~~~~~~~~~~~~~~~~~~
| number;
~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type I1 = string & () => void;
~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type I2 = string & (...foo: number[]) => void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type I3 = & () => boolean
~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type I4 = & () => boolean & null;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type I5 = string & (any: any, any2: any) => any & any;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type I6 =
& string
& (foo: any) => void;
~~~~~~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type M1 = string | number & string | () => number;
~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type M2 = any & string | any & () => void;
~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
type M3 = any & (foo: any) => void | () => void & any;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1387: Function type notation must be parenthesized when used in an intersection type.
~~~~~~~~~~~~~~~~~
!!! error TS1385: Function type notation must be parenthesized when used in a union type.
type OK1 = string | (number);
type OK2 = string | ((number));
type OK3 = string | (()=> void);
type OK4 = string | (()=> string | number);

View File

@ -0,0 +1,31 @@
//// [unparenthesizedFunctionTypeInUnionOrIntersection.ts]
type U1 = string | () => void;
type U2 = string | (foo: number) => void
type U3 = | () => number
type U4 = | (foo?: number) => void;
type U5 = string | (number: number, foo?: string) => void | number;
type U6 =
| string
| (...args: any[]) => void
| number;
type I1 = string & () => void;
type I2 = string & (...foo: number[]) => void;
type I3 = & () => boolean
type I4 = & () => boolean & null;
type I5 = string & (any: any, any2: any) => any & any;
type I6 =
& string
& (foo: any) => void;
type M1 = string | number & string | () => number;
type M2 = any & string | any & () => void;
type M3 = any & (foo: any) => void | () => void & any;
type OK1 = string | (number);
type OK2 = string | ((number));
type OK3 = string | (()=> void);
type OK4 = string | (()=> string | number);
//// [unparenthesizedFunctionTypeInUnionOrIntersection.js]

View File

@ -0,0 +1,76 @@
=== tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts ===
type U1 = string | () => void;
>U1 : Symbol(U1, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 0, 0))
type U2 = string | (foo: number) => void
>U2 : Symbol(U2, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 0, 30))
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 1, 20))
type U3 = | () => number
>U3 : Symbol(U3, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 1, 40))
type U4 = | (foo?: number) => void;
>U4 : Symbol(U4, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 2, 24))
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 3, 13))
type U5 = string | (number: number, foo?: string) => void | number;
>U5 : Symbol(U5, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 3, 35))
>number : Symbol(number, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 4, 20))
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 4, 35))
type U6 =
>U6 : Symbol(U6, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 4, 67))
| string
| (...args: any[]) => void
>args : Symbol(args, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 7, 5))
| number;
type I1 = string & () => void;
>I1 : Symbol(I1, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 8, 11))
type I2 = string & (...foo: number[]) => void;
>I2 : Symbol(I2, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 10, 30))
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 11, 20))
type I3 = & () => boolean
>I3 : Symbol(I3, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 11, 46))
type I4 = & () => boolean & null;
>I4 : Symbol(I4, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 12, 25))
type I5 = string & (any: any, any2: any) => any & any;
>I5 : Symbol(I5, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 13, 33))
>any : Symbol(any, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 14, 20))
>any2 : Symbol(any2, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 14, 29))
type I6 =
>I6 : Symbol(I6, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 14, 54))
& string
& (foo: any) => void;
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 17, 5))
type M1 = string | number & string | () => number;
>M1 : Symbol(M1, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 17, 23))
type M2 = any & string | any & () => void;
>M2 : Symbol(M2, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 19, 50))
type M3 = any & (foo: any) => void | () => void & any;
>M3 : Symbol(M3, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 20, 42))
>foo : Symbol(foo, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 21, 17))
type OK1 = string | (number);
>OK1 : Symbol(OK1, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 21, 54))
type OK2 = string | ((number));
>OK2 : Symbol(OK2, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 23, 29))
type OK3 = string | (()=> void);
>OK3 : Symbol(OK3, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 24, 31))
type OK4 = string | (()=> string | number);
>OK4 : Symbol(OK4, Decl(unparenthesizedFunctionTypeInUnionOrIntersection.ts, 25, 32))

View File

@ -0,0 +1,77 @@
=== tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts ===
type U1 = string | () => void;
>U1 : U1
type U2 = string | (foo: number) => void
>U2 : U2
>foo : number
type U3 = | () => number
>U3 : () => number
type U4 = | (foo?: number) => void;
>U4 : (foo?: number) => void
>foo : number
type U5 = string | (number: number, foo?: string) => void | number;
>U5 : U5
>number : number
>foo : string
type U6 =
>U6 : U6
| string
| (...args: any[]) => void
>args : any[]
| number;
type I1 = string & () => void;
>I1 : I1
type I2 = string & (...foo: number[]) => void;
>I2 : I2
>foo : number[]
type I3 = & () => boolean
>I3 : () => boolean
type I4 = & () => boolean & null;
>I4 : () => boolean & null
>null : null
type I5 = string & (any: any, any2: any) => any & any;
>I5 : I5
>any : any
>any2 : any
type I6 =
>I6 : I6
& string
& (foo: any) => void;
>foo : any
type M1 = string | number & string | () => number;
>M1 : M1
type M2 = any & string | any & () => void;
>M2 : any
type M3 = any & (foo: any) => void | () => void & any;
>M3 : any
>foo : any
type OK1 = string | (number);
>OK1 : OK1
type OK2 = string | ((number));
>OK2 : OK1
type OK3 = string | (()=> void);
>OK3 : OK3
type OK4 = string | (()=> string | number);
>OK4 : OK4

View File

@ -0,0 +1,25 @@
type U1 = string | new () => void;
type U2 = string | new (foo: number) => void
type U3 = | new () => number
type U4 = | new (foo?: number) => void;
type U5 = string | new (number: number, foo?: string) => void | number;
type U6 =
| string
| new (...args: any[]) => void
| number;
type I1 = string & new () => void;
type I2 = string & new (...foo: number[]) => void;
type I3 = & new () => boolean
type I4 = & new () => boolean & null;
type I5 = string & new (any: any, any2: any) => any & any;
type I6 =
& string
& new (foo: any) => void;
type M1 = string | number & string | new () => number;
type M2 = any & string | any & new () => void;
type M3 = any & new (foo: any) => void | new () => void & any;
type OK1 = string | (new ()=> void);
type OK2 = string | (new ()=> string | number);

View File

@ -0,0 +1,27 @@
type U1 = string | () => void;
type U2 = string | (foo: number) => void
type U3 = | () => number
type U4 = | (foo?: number) => void;
type U5 = string | (number: number, foo?: string) => void | number;
type U6 =
| string
| (...args: any[]) => void
| number;
type I1 = string & () => void;
type I2 = string & (...foo: number[]) => void;
type I3 = & () => boolean
type I4 = & () => boolean & null;
type I5 = string & (any: any, any2: any) => any & any;
type I6 =
& string
& (foo: any) => void;
type M1 = string | number & string | () => number;
type M2 = any & string | any & () => void;
type M3 = any & (foo: any) => void | () => void & any;
type OK1 = string | (number);
type OK2 = string | ((number));
type OK3 = string | (()=> void);
type OK4 = string | (()=> string | number);