diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cc5ed962ab91a..657302401e18a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8f7ea52ebe94b..bf353c8e0ff13 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -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) => 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(); diff --git a/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.errors.txt b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.errors.txt new file mode 100644 index 0000000000000..df9d2510c60f7 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.errors.txt @@ -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); + \ No newline at end of file diff --git a/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.js b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.js new file mode 100644 index 0000000000000..a16c26e47ac60 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.js @@ -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] diff --git a/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.symbols b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.symbols new file mode 100644 index 0000000000000..1719b440df9d0 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.symbols @@ -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)) + diff --git a/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.types b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.types new file mode 100644 index 0000000000000..bc133b3fe8218 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedConstructorTypeInUnionOrIntersection.types @@ -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 + diff --git a/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.errors.txt b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.errors.txt new file mode 100644 index 0000000000000..b6e08947b612b --- /dev/null +++ b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.errors.txt @@ -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); + \ No newline at end of file diff --git a/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.js b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.js new file mode 100644 index 0000000000000..8e9132059575a --- /dev/null +++ b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.js @@ -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] diff --git a/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.symbols b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.symbols new file mode 100644 index 0000000000000..521f10a322e18 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.symbols @@ -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)) + diff --git a/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.types b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.types new file mode 100644 index 0000000000000..40dd867a696a8 --- /dev/null +++ b/tests/baselines/reference/unparenthesizedFunctionTypeInUnionOrIntersection.types @@ -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 + diff --git a/tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts b/tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts new file mode 100644 index 0000000000000..0c24b47804fa8 --- /dev/null +++ b/tests/cases/compiler/unparenthesizedConstructorTypeInUnionOrIntersection.ts @@ -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); diff --git a/tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts b/tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts new file mode 100644 index 0000000000000..861f7e8cc2020 --- /dev/null +++ b/tests/cases/compiler/unparenthesizedFunctionTypeInUnionOrIntersection.ts @@ -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);