diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e989c8c8a04..9d101aab909 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1990,7 +1990,7 @@ namespace ts { } if (pos < end) { writePunctuation(writer, SyntaxKind.LessThanToken); - writeType(typeArguments[pos], TypeFormatFlags.None); + writeType(typeArguments[pos], TypeFormatFlags.InFirstTypeArgument); pos++; while (pos < end) { writePunctuation(writer, SyntaxKind.CommaToken); @@ -2143,6 +2143,19 @@ namespace ts { } } + function shouldAddParenthesisAroundFunctionType(callSignature: Signature, flags: TypeFormatFlags) { + if (flags & TypeFormatFlags.InElementType) { + return true; + } + else if (flags & TypeFormatFlags.InFirstTypeArgument) { + // Add parenthesis around function type for the first type argument to avoid ambiguity + const typeParameters = callSignature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature) ? + callSignature.target.typeParameters : callSignature.typeParameters; + return typeParameters && typeParameters.length !== 0; + } + return false; + } + function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) { const resolved = resolveStructuredTypeMembers(type); if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { @@ -2153,11 +2166,12 @@ namespace ts { } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { - if (flags & TypeFormatFlags.InElementType) { + const parenthesizeSignature = shouldAddParenthesisAroundFunctionType(resolved.callSignatures[0], flags); + if (parenthesizeSignature) { writePunctuation(writer, SyntaxKind.OpenParenToken); } buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack); - if (flags & TypeFormatFlags.InElementType) { + if (parenthesizeSignature) { writePunctuation(writer, SyntaxKind.CloseParenToken); } return; @@ -2317,12 +2331,14 @@ namespace ts { function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { if (typeParameters && typeParameters.length) { writePunctuation(writer, SyntaxKind.LessThanToken); + let flags = TypeFormatFlags.InFirstTypeArgument; for (let i = 0; i < typeParameters.length; i++) { if (i > 0) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); + flags = TypeFormatFlags.None; } - buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, TypeFormatFlags.None); + buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, flags); } writePunctuation(writer, SyntaxKind.GreaterThanToken); } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 38df2e45d48..58ce2286627 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1377,6 +1377,7 @@ namespace ts { function emitSignatureDeclaration(node: SignatureDeclaration) { const prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; + let closeParenthesizedFunctionType = false; if (node.kind === SyntaxKind.IndexSignature) { // Index signature can have readonly modifier @@ -1388,6 +1389,16 @@ namespace ts { if (node.kind === SyntaxKind.ConstructSignature || node.kind === SyntaxKind.ConstructorType) { write("new "); } + else if (node.kind === SyntaxKind.FunctionType) { + const currentOutput = writer.getText(); + // Do not generate incorrect type when function type with type parameters is type argument + // This could happen if user used space between two '<' making it error free + // e.g var x: A< (a: Tany)=>Tany>; + if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") { + closeParenthesizedFunctionType = true; + write("("); + } + } emitTypeParameters(node.typeParameters); write("("); } @@ -1421,6 +1432,9 @@ namespace ts { write(";"); writeLine(); } + else if (closeParenthesizedFunctionType) { + write(")"); + } function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 718be453b09..c39a4b10cbf 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1820,6 +1820,7 @@ namespace ts { WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature InElementType = 0x00000040, // Writing an array or union element type UseFullyQualifiedType = 0x00000080, // Write out the fully qualified type name (eg. Module.Type, instead of Type) + InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type } export const enum SymbolFormatFlags { diff --git a/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.js b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.js new file mode 100644 index 00000000000..b2bca641a5a --- /dev/null +++ b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.js @@ -0,0 +1,66 @@ +//// [declarationEmitFirstTypeArgumentGenericFunctionType.ts] + +class X { +} +var prop11: X< () => Tany >; // spaces before the first type argument +var prop12: X<(() => Tany)>; // spaces before the first type argument +function f1() { // Inferred return type + return prop11; +} +function f2() { // Inferred return type + return prop12; +} +function f3(): X< () => Tany> { // written with space before type argument + return prop11; +} +function f4(): X<(() => Tany)> { // written type with parenthesis + return prop12; +} +class Y { +} +var prop2: Y() => Tany>; // No space after second type argument +var prop2: Y() => Tany>; // space after second type argument +var prop3: Y< () => Tany, () => Tany>; // space before first type argument +var prop4: Y<(() => Tany), () => Tany>; // parenthesized first type argument + + +//// [declarationEmitFirstTypeArgumentGenericFunctionType.js] +class X { +} +var prop11; // spaces before the first type argument +var prop12; // spaces before the first type argument +function f1() { + return prop11; +} +function f2() { + return prop12; +} +function f3() { + return prop11; +} +function f4() { + return prop12; +} +class Y { +} +var prop2; // No space after second type argument +var prop2; // space after second type argument +var prop3; // space before first type argument +var prop4; // parenthesized first type argument + + +//// [declarationEmitFirstTypeArgumentGenericFunctionType.d.ts] +declare class X { +} +declare var prop11: X<(() => Tany)>; +declare var prop12: X<(() => Tany)>; +declare function f1(): X<(() => Tany)>; +declare function f2(): X<(() => Tany)>; +declare function f3(): X<(() => Tany)>; +declare function f4(): X<(() => Tany)>; +declare class Y { +} +declare var prop2: Y() => Tany>; +declare var prop2: Y() => Tany>; +declare var prop3: Y<(() => Tany), () => Tany>; +declare var prop4: Y<(() => Tany), () => Tany>; diff --git a/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.symbols b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.symbols new file mode 100644 index 00000000000..ebbc2b764b0 --- /dev/null +++ b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.symbols @@ -0,0 +1,81 @@ +=== tests/cases/compiler/declarationEmitFirstTypeArgumentGenericFunctionType.ts === + +class X { +>X : Symbol(X, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 0, 0)) +>A : Symbol(A, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 1, 8)) +} +var prop11: X< () => Tany >; // spaces before the first type argument +>prop11 : Symbol(prop11, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 3, 3)) +>X : Symbol(X, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 0, 0)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 3, 16)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 3, 16)) + +var prop12: X<(() => Tany)>; // spaces before the first type argument +>prop12 : Symbol(prop12, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 3)) +>X : Symbol(X, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 0, 0)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 16)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 16)) + +function f1() { // Inferred return type +>f1 : Symbol(f1, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 34)) + + return prop11; +>prop11 : Symbol(prop11, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 3, 3)) +} +function f2() { // Inferred return type +>f2 : Symbol(f2, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 7, 1)) + + return prop12; +>prop12 : Symbol(prop12, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 3)) +} +function f3(): X< () => Tany> { // written with space before type argument +>f3 : Symbol(f3, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 10, 1)) +>X : Symbol(X, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 0, 0)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 11, 19)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 11, 19)) + + return prop11; +>prop11 : Symbol(prop11, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 3, 3)) +} +function f4(): X<(() => Tany)> { // written type with parenthesis +>f4 : Symbol(f4, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 13, 1)) +>X : Symbol(X, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 0, 0)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 14, 19)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 14, 19)) + + return prop12; +>prop12 : Symbol(prop12, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 4, 3)) +} +class Y { +>Y : Symbol(Y, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 16, 1)) +>A : Symbol(A, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 17, 8)) +>B : Symbol(B, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 17, 10)) +} +var prop2: Y() => Tany>; // No space after second type argument +>prop2 : Symbol(prop2, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 19, 3), Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 20, 3)) +>Y : Symbol(Y, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 16, 1)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 19, 24)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 19, 24)) + +var prop2: Y() => Tany>; // space after second type argument +>prop2 : Symbol(prop2, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 19, 3), Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 20, 3)) +>Y : Symbol(Y, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 16, 1)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 20, 24)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 20, 24)) + +var prop3: Y< () => Tany, () => Tany>; // space before first type argument +>prop3 : Symbol(prop3, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 21, 3)) +>Y : Symbol(Y, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 16, 1)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 21, 15)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 21, 15)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 21, 33)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 21, 33)) + +var prop4: Y<(() => Tany), () => Tany>; // parenthesized first type argument +>prop4 : Symbol(prop4, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 22, 3)) +>Y : Symbol(Y, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 16, 1)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 22, 15)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 22, 15)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 22, 34)) +>Tany : Symbol(Tany, Decl(declarationEmitFirstTypeArgumentGenericFunctionType.ts, 22, 34)) + diff --git a/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.types b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.types new file mode 100644 index 00000000000..4dd6ecba987 --- /dev/null +++ b/tests/baselines/reference/declarationEmitFirstTypeArgumentGenericFunctionType.types @@ -0,0 +1,81 @@ +=== tests/cases/compiler/declarationEmitFirstTypeArgumentGenericFunctionType.ts === + +class X { +>X : X +>A : A +} +var prop11: X< () => Tany >; // spaces before the first type argument +>prop11 : X<(() => Tany)> +>X : X +>Tany : Tany +>Tany : Tany + +var prop12: X<(() => Tany)>; // spaces before the first type argument +>prop12 : X<(() => Tany)> +>X : X +>Tany : Tany +>Tany : Tany + +function f1() { // Inferred return type +>f1 : () => X<(() => Tany)> + + return prop11; +>prop11 : X<(() => Tany)> +} +function f2() { // Inferred return type +>f2 : () => X<(() => Tany)> + + return prop12; +>prop12 : X<(() => Tany)> +} +function f3(): X< () => Tany> { // written with space before type argument +>f3 : () => X<(() => Tany)> +>X : X +>Tany : Tany +>Tany : Tany + + return prop11; +>prop11 : X<(() => Tany)> +} +function f4(): X<(() => Tany)> { // written type with parenthesis +>f4 : () => X<(() => Tany)> +>X : X +>Tany : Tany +>Tany : Tany + + return prop12; +>prop12 : X<(() => Tany)> +} +class Y { +>Y : Y +>A : A +>B : B +} +var prop2: Y() => Tany>; // No space after second type argument +>prop2 : Y() => Tany> +>Y : Y +>Tany : Tany +>Tany : Tany + +var prop2: Y() => Tany>; // space after second type argument +>prop2 : Y() => Tany> +>Y : Y +>Tany : Tany +>Tany : Tany + +var prop3: Y< () => Tany, () => Tany>; // space before first type argument +>prop3 : Y<(() => Tany), () => Tany> +>Y : Y +>Tany : Tany +>Tany : Tany +>Tany : Tany +>Tany : Tany + +var prop4: Y<(() => Tany), () => Tany>; // parenthesized first type argument +>prop4 : Y<(() => Tany), () => Tany> +>Y : Y +>Tany : Tany +>Tany : Tany +>Tany : Tany +>Tany : Tany + diff --git a/tests/baselines/reference/declarationEmitPromise.js b/tests/baselines/reference/declarationEmitPromise.js new file mode 100644 index 00000000000..a4bbdd74dde --- /dev/null +++ b/tests/baselines/reference/declarationEmitPromise.js @@ -0,0 +1,63 @@ +//// [declarationEmitPromise.ts] + +export class bluebird { + static all: Array>; +} + +export async function runSampleWorks( + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => + f.apply(this, result); + let rfunc: typeof func & {} = func as any; // <- This is the only difference + return rfunc +} + +export async function runSampleBreaks( + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => + f.apply(this, result); + let rfunc: typeof func = func as any; // <- This is the only difference + return rfunc +} + +//// [declarationEmitPromise.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +class bluebird { +} +exports.bluebird = bluebird; +function runSampleWorks(a, b, c, d, e) { + return __awaiter(this, void 0, void 0, function* () { + let result = yield bluebird.all([a, b, c, d, e].filter(el => !!el)); + let func = (f) => f.apply(this, result); + let rfunc = func; // <- This is the only difference + return rfunc; + }); +} +exports.runSampleWorks = runSampleWorks; +function runSampleBreaks(a, b, c, d, e) { + return __awaiter(this, void 0, void 0, function* () { + let result = yield bluebird.all([a, b, c, d, e].filter(el => !!el)); + let func = (f) => f.apply(this, result); + let rfunc = func; // <- This is the only difference + return rfunc; + }); +} +exports.runSampleBreaks = runSampleBreaks; + + +//// [declarationEmitPromise.d.ts] +export declare class bluebird { + static all: Array>; +} +export declare function runSampleWorks(a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird): Promise<((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T) & {}>; +export declare function runSampleBreaks(a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird): Promise<((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T)>; diff --git a/tests/baselines/reference/declarationEmitPromise.symbols b/tests/baselines/reference/declarationEmitPromise.symbols new file mode 100644 index 00000000000..894a20e03a6 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPromise.symbols @@ -0,0 +1,155 @@ +=== tests/cases/compiler/declarationEmitPromise.ts === + +export class bluebird { +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 1, 22)) + + static all: Array>; +>all : Symbol(bluebird.all, Decl(declarationEmitPromise.ts, 1, 26)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +} + +export async function runSampleWorks( +>runSampleWorks : Symbol(runSampleWorks, Decl(declarationEmitPromise.ts, 3, 1)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 5, 37)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 5, 39)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 5, 42)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 5, 45)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 5, 48)) + + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { +>a : Symbol(a, Decl(declarationEmitPromise.ts, 5, 52)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 5, 37)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 6, 19)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 5, 39)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 6, 36)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 5, 42)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 6, 53)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 5, 45)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 6, 70)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 5, 48)) + + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); +>result : Symbol(result, Decl(declarationEmitPromise.ts, 7, 7)) +>bluebird.all : Symbol(bluebird.all, Decl(declarationEmitPromise.ts, 1, 26)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>all : Symbol(bluebird.all, Decl(declarationEmitPromise.ts, 1, 26)) +>[a, b, c, d, e].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(declarationEmitPromise.ts, 5, 52)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 6, 19)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 6, 36)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 6, 53)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 6, 70)) +>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --)) +>el : Symbol(el, Decl(declarationEmitPromise.ts, 7, 68)) +>el : Symbol(el, Decl(declarationEmitPromise.ts, 7, 68)) + + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => +>func : Symbol(func, Decl(declarationEmitPromise.ts, 8, 7)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 8, 16)) +>f : Symbol(f, Decl(declarationEmitPromise.ts, 8, 19)) +>a : Symbol(a, Decl(declarationEmitPromise.ts, 8, 23)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 5, 37)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 8, 28)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 5, 39)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 8, 35)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 5, 42)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 8, 42)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 5, 45)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 8, 49)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 5, 48)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 8, 16)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 8, 16)) + + f.apply(this, result); +>f.apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>f : Symbol(f, Decl(declarationEmitPromise.ts, 8, 19)) +>apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>result : Symbol(result, Decl(declarationEmitPromise.ts, 7, 7)) + + let rfunc: typeof func & {} = func as any; // <- This is the only difference +>rfunc : Symbol(rfunc, Decl(declarationEmitPromise.ts, 10, 7)) +>func : Symbol(func, Decl(declarationEmitPromise.ts, 8, 7)) +>func : Symbol(func, Decl(declarationEmitPromise.ts, 8, 7)) + + return rfunc +>rfunc : Symbol(rfunc, Decl(declarationEmitPromise.ts, 10, 7)) +} + +export async function runSampleBreaks( +>runSampleBreaks : Symbol(runSampleBreaks, Decl(declarationEmitPromise.ts, 12, 1)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 14, 38)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 14, 40)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 14, 43)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 14, 46)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 14, 49)) + + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { +>a : Symbol(a, Decl(declarationEmitPromise.ts, 14, 53)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 14, 38)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 15, 19)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 14, 40)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 15, 36)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 14, 43)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 15, 53)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 14, 46)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 15, 70)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 14, 49)) + + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); +>result : Symbol(result, Decl(declarationEmitPromise.ts, 16, 7)) +>bluebird.all : Symbol(bluebird.all, Decl(declarationEmitPromise.ts, 1, 26)) +>bluebird : Symbol(bluebird, Decl(declarationEmitPromise.ts, 0, 0)) +>all : Symbol(bluebird.all, Decl(declarationEmitPromise.ts, 1, 26)) +>[a, b, c, d, e].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(declarationEmitPromise.ts, 14, 53)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 15, 19)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 15, 36)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 15, 53)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 15, 70)) +>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --)) +>el : Symbol(el, Decl(declarationEmitPromise.ts, 16, 68)) +>el : Symbol(el, Decl(declarationEmitPromise.ts, 16, 68)) + + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => +>func : Symbol(func, Decl(declarationEmitPromise.ts, 17, 7)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 17, 16)) +>f : Symbol(f, Decl(declarationEmitPromise.ts, 17, 19)) +>a : Symbol(a, Decl(declarationEmitPromise.ts, 17, 23)) +>A : Symbol(A, Decl(declarationEmitPromise.ts, 14, 38)) +>b : Symbol(b, Decl(declarationEmitPromise.ts, 17, 28)) +>B : Symbol(B, Decl(declarationEmitPromise.ts, 14, 40)) +>c : Symbol(c, Decl(declarationEmitPromise.ts, 17, 35)) +>C : Symbol(C, Decl(declarationEmitPromise.ts, 14, 43)) +>d : Symbol(d, Decl(declarationEmitPromise.ts, 17, 42)) +>D : Symbol(D, Decl(declarationEmitPromise.ts, 14, 46)) +>e : Symbol(e, Decl(declarationEmitPromise.ts, 17, 49)) +>E : Symbol(E, Decl(declarationEmitPromise.ts, 14, 49)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 17, 16)) +>T : Symbol(T, Decl(declarationEmitPromise.ts, 17, 16)) + + f.apply(this, result); +>f.apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>f : Symbol(f, Decl(declarationEmitPromise.ts, 17, 19)) +>apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>result : Symbol(result, Decl(declarationEmitPromise.ts, 16, 7)) + + let rfunc: typeof func = func as any; // <- This is the only difference +>rfunc : Symbol(rfunc, Decl(declarationEmitPromise.ts, 19, 7)) +>func : Symbol(func, Decl(declarationEmitPromise.ts, 17, 7)) +>func : Symbol(func, Decl(declarationEmitPromise.ts, 17, 7)) + + return rfunc +>rfunc : Symbol(rfunc, Decl(declarationEmitPromise.ts, 19, 7)) +} diff --git a/tests/baselines/reference/declarationEmitPromise.types b/tests/baselines/reference/declarationEmitPromise.types new file mode 100644 index 00000000000..0306c72762b --- /dev/null +++ b/tests/baselines/reference/declarationEmitPromise.types @@ -0,0 +1,181 @@ +=== tests/cases/compiler/declarationEmitPromise.ts === + +export class bluebird { +>bluebird : bluebird +>T : T + + static all: Array>; +>all : bluebird[] +>Array : T[] +>bluebird : bluebird +} + +export async function runSampleWorks( +>runSampleWorks : (a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) => Promise<((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T) & {}> +>A : A +>B : B +>C : C +>D : D +>E : E + + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { +>a : bluebird +>bluebird : bluebird +>A : A +>b : bluebird +>bluebird : bluebird +>B : B +>c : bluebird +>bluebird : bluebird +>C : C +>d : bluebird +>bluebird : bluebird +>D : D +>e : bluebird +>bluebird : bluebird +>E : E + + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); +>result : any +>await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)) : any +>(bluebird.all as any)([a, b, c, d, e].filter(el => !!el)) : any +>(bluebird.all as any) : any +>bluebird.all as any : any +>bluebird.all : bluebird[] +>bluebird : typeof bluebird +>all : bluebird[] +>[a, b, c, d, e].filter(el => !!el) : bluebird[] +>[a, b, c, d, e].filter : (callbackfn: (value: bluebird, index: number, array: bluebird[]) => any, thisArg?: any) => bluebird[] +>[a, b, c, d, e] : bluebird[] +>a : bluebird +>b : bluebird +>c : bluebird +>d : bluebird +>e : bluebird +>filter : (callbackfn: (value: bluebird, index: number, array: bluebird[]) => any, thisArg?: any) => bluebird[] +>el => !!el : (el: bluebird) => boolean +>el : bluebird +>!!el : boolean +>!el : boolean +>el : bluebird + + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => f.apply(this, result) : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>T : T +>f : (a: A, b?: B, c?: C, d?: D, e?: E) => T +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +>d : D +>D : D +>e : E +>E : E +>T : T +>T : T + + f.apply(this, result); +>f.apply(this, result) : T +>f.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>f : (a: A, b?: B, c?: C, d?: D, e?: E) => T +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>this : any +>result : any + + let rfunc: typeof func & {} = func as any; // <- This is the only difference +>rfunc : ((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T) & {} +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>func as any : any +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T + + return rfunc +>rfunc : ((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T) & {} +} + +export async function runSampleBreaks( +>runSampleBreaks : (a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) => Promise<((f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T)> +>A : A +>B : B +>C : C +>D : D +>E : E + + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { +>a : bluebird +>bluebird : bluebird +>A : A +>b : bluebird +>bluebird : bluebird +>B : B +>c : bluebird +>bluebird : bluebird +>C : C +>d : bluebird +>bluebird : bluebird +>D : D +>e : bluebird +>bluebird : bluebird +>E : E + + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); +>result : any +>await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)) : any +>(bluebird.all as any)([a, b, c, d, e].filter(el => !!el)) : any +>(bluebird.all as any) : any +>bluebird.all as any : any +>bluebird.all : bluebird[] +>bluebird : typeof bluebird +>all : bluebird[] +>[a, b, c, d, e].filter(el => !!el) : bluebird[] +>[a, b, c, d, e].filter : (callbackfn: (value: bluebird, index: number, array: bluebird[]) => any, thisArg?: any) => bluebird[] +>[a, b, c, d, e] : bluebird[] +>a : bluebird +>b : bluebird +>c : bluebird +>d : bluebird +>e : bluebird +>filter : (callbackfn: (value: bluebird, index: number, array: bluebird[]) => any, thisArg?: any) => bluebird[] +>el => !!el : (el: bluebird) => boolean +>el : bluebird +>!!el : boolean +>!el : boolean +>el : bluebird + + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>(f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => f.apply(this, result) : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>T : T +>f : (a: A, b?: B, c?: C, d?: D, e?: E) => T +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +>d : D +>D : D +>e : E +>E : E +>T : T +>T : T + + f.apply(this, result); +>f.apply(this, result) : T +>f.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>f : (a: A, b?: B, c?: C, d?: D, e?: E) => T +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>this : any +>result : any + + let rfunc: typeof func = func as any; // <- This is the only difference +>rfunc : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +>func as any : any +>func : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T + + return rfunc +>rfunc : (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T) => T +} diff --git a/tests/baselines/reference/specializedLambdaTypeArguments.types b/tests/baselines/reference/specializedLambdaTypeArguments.types index 3eb2fbc959e..b10da421044 100644 --- a/tests/baselines/reference/specializedLambdaTypeArguments.types +++ b/tests/baselines/reference/specializedLambdaTypeArguments.types @@ -4,7 +4,7 @@ class X { >A : A prop: X< () => Tany >; ->prop : X<() => Tany> +>prop : X<(() => Tany)> >X : X >Tany : Tany >Tany : Tany diff --git a/tests/cases/compiler/declarationEmitFirstTypeArgumentGenericFunctionType.ts b/tests/cases/compiler/declarationEmitFirstTypeArgumentGenericFunctionType.ts new file mode 100644 index 00000000000..3c5100d0772 --- /dev/null +++ b/tests/cases/compiler/declarationEmitFirstTypeArgumentGenericFunctionType.ts @@ -0,0 +1,26 @@ +// @declaration: true +// @module: commonjs +// @target: es6 + +class X { +} +var prop11: X< () => Tany >; // spaces before the first type argument +var prop12: X<(() => Tany)>; // spaces before the first type argument +function f1() { // Inferred return type + return prop11; +} +function f2() { // Inferred return type + return prop12; +} +function f3(): X< () => Tany> { // written with space before type argument + return prop11; +} +function f4(): X<(() => Tany)> { // written type with parenthesis + return prop12; +} +class Y { +} +var prop2: Y() => Tany>; // No space after second type argument +var prop2: Y() => Tany>; // space after second type argument +var prop3: Y< () => Tany, () => Tany>; // space before first type argument +var prop4: Y<(() => Tany), () => Tany>; // parenthesized first type argument diff --git a/tests/cases/compiler/declarationEmitPromise.ts b/tests/cases/compiler/declarationEmitPromise.ts new file mode 100644 index 00000000000..2eff0b6c50c --- /dev/null +++ b/tests/cases/compiler/declarationEmitPromise.ts @@ -0,0 +1,25 @@ +// @declaration: true +// @module: commonjs +// @target: es6 + +export class bluebird { + static all: Array>; +} + +export async function runSampleWorks( + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => + f.apply(this, result); + let rfunc: typeof func & {} = func as any; // <- This is the only difference + return rfunc +} + +export async function runSampleBreaks( + a: bluebird, b?: bluebird, c?: bluebird, d?: bluebird, e?: bluebird) { + let result = await (bluebird.all as any)([a, b, c, d, e].filter(el => !!el)); + let func = (f: (a: A, b?: B, c?: C, d?: D, e?: E) => T): T => + f.apply(this, result); + let rfunc: typeof func = func as any; // <- This is the only difference + return rfunc +} \ No newline at end of file