From 842cf177dbbe15f66dfade0ee6aea2bc903a42bf Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Fri, 24 May 2024 21:50:47 +0300 Subject: [PATCH] Improved errors for required parameters with default values in isolated declaration (#58637) --- src/compiler/checker.ts | 12 +- src/compiler/expressionToTypeNode.ts | 15 +- ...solatedDeclarationsAddUndefined.errors.txt | 10 +- .../isolatedDeclarationsAddUndefined.js | 8 + .../isolatedDeclarationsAddUndefined.symbols | 16 +- .../isolatedDeclarationsAddUndefined.types | 20 ++ .../declarationFunctionDeclarations.d.ts | 213 ++++++++++++++++++ .../declarationFunctionDeclarations.js | 120 ++++++++++ .../isolatedDeclarationsAddUndefined.ts | 2 + .../declarationFunctionDeclarations.ts | 51 +++++ 10 files changed, 446 insertions(+), 21 deletions(-) create mode 100644 tests/baselines/reference/transpile/declarationFunctionDeclarations.d.ts create mode 100644 tests/baselines/reference/transpile/declarationFunctionDeclarations.js create mode 100644 tests/cases/transpile/declarationFunctionDeclarations.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86acdb7c44b..85c437de9be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6116,7 +6116,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } } - context.tracker.reportInferenceFallback(existing); return undefined; } @@ -8217,6 +8216,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function serializeTypeForDeclaration(context: NodeBuilderContext, declaration: Declaration | undefined, type: Type, symbol: Symbol) { const addUndefined = declaration && (isParameter(declaration) || isJSDocParameterTag(declaration)) && requiresAddingImplicitUndefined(declaration); const enclosingDeclaration = context.enclosingDeclaration; + const oldFlags = context.flags; + if (declaration && hasInferredType(declaration) && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) { + syntacticNodeBuilder.serializeTypeOfDeclaration(declaration, context); + } + context.flags |= NodeBuilderFlags.NoSyntacticPrinter; if (enclosingDeclaration && (!isErrorType(type) || (context.flags & NodeBuilderFlags.AllowUnresolvedNames))) { const declWithExistingAnnotation = declaration && getNonlocalEffectiveTypeAnnotationNode(declaration) ? declaration @@ -8226,11 +8230,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const existing = getNonlocalEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; const result = !isTypePredicateNode(existing) && tryReuseExistingTypeNode(context, existing, type, declWithExistingAnnotation, addUndefined); if (result) { + context.flags = oldFlags; return result; } } } - const oldFlags = context.flags; if ( type.flags & TypeFlags.UniqueESSymbol && type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!))) @@ -8241,10 +8245,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const decl = declaration ?? symbol.valueDeclaration ?? symbol.declarations?.[0]; const expr = decl && isDeclarationWithPossibleInnerTypeNodeReuse(decl) ? getPossibleTypeNodeReuseExpression(decl) : undefined; - if (decl && hasInferredType(decl) && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) { - syntacticNodeBuilder.serializeTypeOfDeclaration(decl, context); - } - context.flags |= NodeBuilderFlags.NoSyntacticPrinter; const result = expressionOrTypeToTypeNode(context, expr, type, addUndefined); context.flags = oldFlags; return result; diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index 982be51efb3..e1a9c0548a7 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -32,7 +32,6 @@ import { isIdentifier, isJSDocTypeAssertion, isKeyword, - isParameter, isPrimitiveLiteralValue, isShorthandPropertyAssignment, isSpreadAssignment, @@ -76,8 +75,8 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve serializeReturnTypeForSignature, serializeTypeOfExpression, }; - function serializeExistingTypeAnnotation(type: TypeNode | undefined) { - return type === undefined ? undefined : !type.parent || !isParameter(type.parent) || !resolver.requiresAddingImplicitUndefined(type.parent) || canAddUndefined(type); + function serializeExistingTypeAnnotation(type: TypeNode | undefined, addUndefined?: boolean) { + return type !== undefined && (!addUndefined || (type && canAddUndefined(type))) ? true : undefined; } function serializeTypeOfExpression(expr: Expression, context: SyntacticTypeNodeBuilderContext, addUndefined?: boolean, preserveLiterals?: boolean) { return typeFromExpression(expr, context, /*isConstContext*/ false, addUndefined, preserveLiterals) ?? inferExpressionType(expr, context); @@ -181,12 +180,12 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve const declaredType = getEffectiveTypeAnnotationNode(node); const addUndefined = resolver.requiresAddingImplicitUndefined(node); let resultType; - if (!addUndefined) { - if (declaredType) { - return serializeExistingTypeAnnotation(declaredType); - } + if (declaredType) { + resultType = serializeExistingTypeAnnotation(declaredType, addUndefined); + } + else { if (node.initializer && isIdentifier(node.name)) { - resultType = typeFromExpression(node.initializer, context); + resultType = typeFromExpression(node.initializer, context, /*isConstContext*/ undefined, addUndefined); } } return resultType ?? inferTypeOfDeclaration(node, context); diff --git a/tests/baselines/reference/isolatedDeclarationsAddUndefined.errors.txt b/tests/baselines/reference/isolatedDeclarationsAddUndefined.errors.txt index 9440b0a5d33..7beba23a985 100644 --- a/tests/baselines/reference/isolatedDeclarationsAddUndefined.errors.txt +++ b/tests/baselines/reference/isolatedDeclarationsAddUndefined.errors.txt @@ -1,4 +1,4 @@ -file2.ts(1,26): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +file2.ts(4,38): error TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations. ==== file1.ts (0 errors) ==== @@ -12,10 +12,12 @@ file2.ts(1,26): error TS9025: Declaration emit for this parameter requires impli ==== file2.ts (1 errors) ==== export function foo(p = (ip = 10, v: number): void => {}): void{ - ~~~~~~~ -!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. -!!! related TS9028 file2.ts:1:26: Add a type annotation to the parameter ip. } + type T = number + export function foo2(p = (ip = 10 as T, v: number): void => {}): void{} + ~ +!!! error TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9028 file2.ts:4:27: Add a type annotation to the parameter ip. export class Bar2 { readonly r = 1; f = 2; diff --git a/tests/baselines/reference/isolatedDeclarationsAddUndefined.js b/tests/baselines/reference/isolatedDeclarationsAddUndefined.js index b338db02c8a..525c702548d 100644 --- a/tests/baselines/reference/isolatedDeclarationsAddUndefined.js +++ b/tests/baselines/reference/isolatedDeclarationsAddUndefined.js @@ -12,6 +12,8 @@ export class Bar { //// [file2.ts] export function foo(p = (ip = 10, v: number): void => {}): void{ } +type T = number +export function foo2(p = (ip = 10 as T, v: number): void => {}): void{} export class Bar2 { readonly r = 1; f = 2; @@ -36,11 +38,17 @@ exports.Bar = Bar; Object.defineProperty(exports, "__esModule", { value: true }); exports.Bar2 = void 0; exports.foo = foo; +exports.foo2 = foo2; function foo(p) { if (p === void 0) { p = function (ip, v) { if (ip === void 0) { ip = 10; } }; } } +function foo2(p) { + if (p === void 0) { p = function (ip, v) { + if (ip === void 0) { ip = 10; } + }; } +} var Bar2 = /** @class */ (function () { function Bar2() { this.r = 1; diff --git a/tests/baselines/reference/isolatedDeclarationsAddUndefined.symbols b/tests/baselines/reference/isolatedDeclarationsAddUndefined.symbols index 3b27ee8bfd3..17bc7ca28c9 100644 --- a/tests/baselines/reference/isolatedDeclarationsAddUndefined.symbols +++ b/tests/baselines/reference/isolatedDeclarationsAddUndefined.symbols @@ -30,12 +30,22 @@ export function foo(p = (ip = 10, v: number): void => {}): void{ >ip : Symbol(ip, Decl(file2.ts, 0, 25)) >v : Symbol(v, Decl(file2.ts, 0, 33)) } +type T = number +>T : Symbol(T, Decl(file2.ts, 1, 1)) + +export function foo2(p = (ip = 10 as T, v: number): void => {}): void{} +>foo2 : Symbol(foo2, Decl(file2.ts, 2, 15)) +>p : Symbol(p, Decl(file2.ts, 3, 21)) +>ip : Symbol(ip, Decl(file2.ts, 3, 26)) +>T : Symbol(T, Decl(file2.ts, 1, 1)) +>v : Symbol(v, Decl(file2.ts, 3, 39)) + export class Bar2 { ->Bar2 : Symbol(Bar2, Decl(file2.ts, 1, 1)) +>Bar2 : Symbol(Bar2, Decl(file2.ts, 3, 71)) readonly r = 1; ->r : Symbol(Bar2.r, Decl(file2.ts, 2, 19)) +>r : Symbol(Bar2.r, Decl(file2.ts, 4, 19)) f = 2; ->f : Symbol(Bar2.f, Decl(file2.ts, 3, 19)) +>f : Symbol(Bar2.f, Decl(file2.ts, 5, 19)) } diff --git a/tests/baselines/reference/isolatedDeclarationsAddUndefined.types b/tests/baselines/reference/isolatedDeclarationsAddUndefined.types index 2c7bebc2bb9..8c2ef0242be 100644 --- a/tests/baselines/reference/isolatedDeclarationsAddUndefined.types +++ b/tests/baselines/reference/isolatedDeclarationsAddUndefined.types @@ -57,6 +57,26 @@ export function foo(p = (ip = 10, v: number): void => {}): void{ >v : number > : ^^^^^^ } +type T = number +>T : number +> : ^^^^^^ + +export function foo2(p = (ip = 10 as T, v: number): void => {}): void{} +>foo2 : (p?: (ip: T | undefined, v: number) => void) => void +> : ^ ^^^^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^ +>p : (ip: T | undefined, v: number) => void +> : ^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^ +>(ip = 10 as T, v: number): void => {} : (ip: T | undefined, v: number) => void +> : ^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^ +>ip : number +> : ^^^^^^ +>10 as T : number +> : ^^^^^^ +>10 : 10 +> : ^^ +>v : number +> : ^^^^^^ + export class Bar2 { >Bar2 : Bar2 > : ^^^^ diff --git a/tests/baselines/reference/transpile/declarationFunctionDeclarations.d.ts b/tests/baselines/reference/transpile/declarationFunctionDeclarations.d.ts new file mode 100644 index 00000000000..0b63bb9527e --- /dev/null +++ b/tests/baselines/reference/transpile/declarationFunctionDeclarations.d.ts @@ -0,0 +1,213 @@ +//// [fnDecl.ts] //// +type T = number[] +export function fnDeclBasic1(p: number[] | string[] | [T] = [], rParam: string): void { }; +export function fnDeclBasic2(p: (n: T) => T = () => null!, rParam: string): void { }; +export function fnDeclBasic3(p: new () => any = class {}, rParam: string): void { }; +export function fnDeclBasic4(p: [T] = [[]], rParam: string): void { }; +export function fnDeclBasic5(p: { a: T } = { a: [] }, rParam: string): void { }; +export function fnDeclBasic6(p: `_${string}` = "_", rParam: string): void { }; +export function fnDeclBasic7(p: { a?: string } & number[] = [], rParam: string): void { }; +export function fnDeclBasic8(p: (number[] | string[]) | number = [], rParam: string): void { }; + +export function fnDeclHasUndefined(p: T | undefined = [], rParam: string): void { }; +export function fnDeclBad(p: T = [], rParam: string): void { }; + +export const fnExprOk1 = function (array: number[] = [], rParam: string): void { }; +export const fnExprOk2 = function (array: T | undefined = [], rParam: string): void { }; +export const fnExprBad = function (array: T = [], rParam: string): void { }; + +export const arrowOk1 = (array: number[] = [], rParam: string): void => { }; +export const arrowOk2 = (array: T | undefined = [], rParam: string): void => { }; +export const arrowBad = (array: T = [], rParam: string): void => { }; + +export const inObjectLiteralFnExprOk1 = { o: function (array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralFnExprOk2 = { o: function (array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralFnExprBad = { o: function (array: T = [], rParam: string): void { } }; + +export const inObjectLiteralArrowOk1 = { o: (array: number[] = [], rParam: string): void => { } }; +export const inObjectLiteralArrowOk2 = { o: (array: T | undefined = [], rParam: string): void => { } }; +export const inObjectLiteralArrowBad = { o: (array: T = [], rParam: string): void => { } }; + +export const inObjectLiteralMethodOk1 = { o(array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralMethodOk2 = { o(array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralMethodBad = { o(array: T = [], rParam: string): void { } }; + + +export class InClassFnExprOk1 { o = function (array: number[] = [], rParam: string): void { } }; +export class InClassFnExprOk2 { o = function (array: T | undefined = [], rParam: string): void { } }; +export class InClassFnExprBad { o = function (array: T = [], rParam: string): void { } }; + +export class InClassArrowOk1 { o = (array: number[] = [], rParam: string): void => { } }; +export class InClassArrowOk2 { o = (array: T | undefined = [], rParam: string): void => { } }; +export class InClassArrowBad { o = (array: T = [], rParam: string): void => { } }; + +export class InClassMethodOk1 { o(array: number[] = [], rParam: string): void { } }; +export class InClassMethodOk2 { o(array: T | undefined = [], rParam: string): void { } }; +export class InClassMethodBad { o(array: T = [], rParam: string): void { } }; + +//// [fnDecl.d.ts] //// +type T = number[]; +export declare function fnDeclBasic1(p: (number[] | string[] | [T]) | undefined, rParam: string): void; +export declare function fnDeclBasic2(p: ((n: T) => T) | undefined, rParam: string): void; +export declare function fnDeclBasic3(p: (new () => any) | undefined, rParam: string): void; +export declare function fnDeclBasic4(p: [T] | undefined, rParam: string): void; +export declare function fnDeclBasic5(p: { + a: T; +} | undefined, rParam: string): void; +export declare function fnDeclBasic6(p: `_${string}` | undefined, rParam: string): void; +export declare function fnDeclBasic7(p: ({ + a?: string; +} & number[]) | undefined, rParam: string): void; +export declare function fnDeclBasic8(p: ((number[] | string[]) | number) | undefined, rParam: string): void; +export declare function fnDeclHasUndefined(p: T | undefined, rParam: string): void; +export declare function fnDeclBad(p: T | undefined, rParam: string): void; +export declare const fnExprOk1: (array: number[] | undefined, rParam: string) => void; +export declare const fnExprOk2: (array: T | undefined, rParam: string) => void; +export declare const fnExprBad: (array: T | undefined, rParam: string) => void; +export declare const arrowOk1: (array: number[] | undefined, rParam: string) => void; +export declare const arrowOk2: (array: T | undefined, rParam: string) => void; +export declare const arrowBad: (array: T | undefined, rParam: string) => void; +export declare const inObjectLiteralFnExprOk1: { + o: (array: number[] | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralFnExprOk2: { + o: (array: T | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralFnExprBad: { + o: (array: T | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralArrowOk1: { + o: (array: number[] | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralArrowOk2: { + o: (array: T | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralArrowBad: { + o: (array: T | undefined, rParam: string) => void; +}; +export declare const inObjectLiteralMethodOk1: { + o(array: number[] | undefined, rParam: string): void; +}; +export declare const inObjectLiteralMethodOk2: { + o(array: T | undefined, rParam: string): void; +}; +export declare const inObjectLiteralMethodBad: { + o(array: T | undefined, rParam: string): void; +}; +export declare class InClassFnExprOk1 { + o: (array: number[] | undefined, rParam: string) => void; +} +export declare class InClassFnExprOk2 { + o: (array: T | undefined, rParam: string) => void; +} +export declare class InClassFnExprBad { + o: (array: T | undefined, rParam: string) => void; +} +export declare class InClassArrowOk1 { + o: (array: number[] | undefined, rParam: string) => void; +} +export declare class InClassArrowOk2 { + o: (array: T | undefined, rParam: string) => void; +} +export declare class InClassArrowBad { + o: (array: T | undefined, rParam: string) => void; +} +export declare class InClassMethodOk1 { + o(array: number[] | undefined, rParam: string): void; +} +export declare class InClassMethodOk2 { + o(array: T | undefined, rParam: string): void; +} +export declare class InClassMethodBad { + o(array: T | undefined, rParam: string): void; +} +export {}; + + +//// [Diagnostics reported] +fnDecl.ts(12,27): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(16,36): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(20,26): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(24,56): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(28,46): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(32,45): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(37,47): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(41,37): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +fnDecl.ts(45,35): error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. + + +==== fnDecl.ts (9 errors) ==== + type T = number[] + export function fnDeclBasic1(p: number[] | string[] | [T] = [], rParam: string): void { }; + export function fnDeclBasic2(p: (n: T) => T = () => null!, rParam: string): void { }; + export function fnDeclBasic3(p: new () => any = class {}, rParam: string): void { }; + export function fnDeclBasic4(p: [T] = [[]], rParam: string): void { }; + export function fnDeclBasic5(p: { a: T } = { a: [] }, rParam: string): void { }; + export function fnDeclBasic6(p: `_${string}` = "_", rParam: string): void { }; + export function fnDeclBasic7(p: { a?: string } & number[] = [], rParam: string): void { }; + export function fnDeclBasic8(p: (number[] | string[]) | number = [], rParam: string): void { }; + + export function fnDeclHasUndefined(p: T | undefined = [], rParam: string): void { }; + export function fnDeclBad(p: T = [], rParam: string): void { }; + ~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:12:27: Add a type annotation to the parameter p. + + export const fnExprOk1 = function (array: number[] = [], rParam: string): void { }; + export const fnExprOk2 = function (array: T | undefined = [], rParam: string): void { }; + export const fnExprBad = function (array: T = [], rParam: string): void { }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:16:36: Add a type annotation to the parameter array. + + export const arrowOk1 = (array: number[] = [], rParam: string): void => { }; + export const arrowOk2 = (array: T | undefined = [], rParam: string): void => { }; + export const arrowBad = (array: T = [], rParam: string): void => { }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:20:26: Add a type annotation to the parameter array. + + export const inObjectLiteralFnExprOk1 = { o: function (array: number[] = [], rParam: string): void { } }; + export const inObjectLiteralFnExprOk2 = { o: function (array: T | undefined = [], rParam: string): void { } }; + export const inObjectLiteralFnExprBad = { o: function (array: T = [], rParam: string): void { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:24:56: Add a type annotation to the parameter array. + + export const inObjectLiteralArrowOk1 = { o: (array: number[] = [], rParam: string): void => { } }; + export const inObjectLiteralArrowOk2 = { o: (array: T | undefined = [], rParam: string): void => { } }; + export const inObjectLiteralArrowBad = { o: (array: T = [], rParam: string): void => { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:28:46: Add a type annotation to the parameter array. + + export const inObjectLiteralMethodOk1 = { o(array: number[] = [], rParam: string): void { } }; + export const inObjectLiteralMethodOk2 = { o(array: T | undefined = [], rParam: string): void { } }; + export const inObjectLiteralMethodBad = { o(array: T = [], rParam: string): void { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:32:45: Add a type annotation to the parameter array. + + + export class InClassFnExprOk1 { o = function (array: number[] = [], rParam: string): void { } }; + export class InClassFnExprOk2 { o = function (array: T | undefined = [], rParam: string): void { } }; + export class InClassFnExprBad { o = function (array: T = [], rParam: string): void { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:37:47: Add a type annotation to the parameter array. + + export class InClassArrowOk1 { o = (array: number[] = [], rParam: string): void => { } }; + export class InClassArrowOk2 { o = (array: T | undefined = [], rParam: string): void => { } }; + export class InClassArrowBad { o = (array: T = [], rParam: string): void => { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:41:37: Add a type annotation to the parameter array. + + export class InClassMethodOk1 { o(array: number[] = [], rParam: string): void { } }; + export class InClassMethodOk2 { o(array: T | undefined = [], rParam: string): void { } }; + export class InClassMethodBad { o(array: T = [], rParam: string): void { } }; + ~~~~~~~~~~~~~ +!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations. +!!! related TS9028 fnDecl.ts:45:35: Add a type annotation to the parameter array. + + diff --git a/tests/baselines/reference/transpile/declarationFunctionDeclarations.js b/tests/baselines/reference/transpile/declarationFunctionDeclarations.js new file mode 100644 index 00000000000..72ba57ff249 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationFunctionDeclarations.js @@ -0,0 +1,120 @@ +//// [fnDecl.ts] //// +type T = number[] +export function fnDeclBasic1(p: number[] | string[] | [T] = [], rParam: string): void { }; +export function fnDeclBasic2(p: (n: T) => T = () => null!, rParam: string): void { }; +export function fnDeclBasic3(p: new () => any = class {}, rParam: string): void { }; +export function fnDeclBasic4(p: [T] = [[]], rParam: string): void { }; +export function fnDeclBasic5(p: { a: T } = { a: [] }, rParam: string): void { }; +export function fnDeclBasic6(p: `_${string}` = "_", rParam: string): void { }; +export function fnDeclBasic7(p: { a?: string } & number[] = [], rParam: string): void { }; +export function fnDeclBasic8(p: (number[] | string[]) | number = [], rParam: string): void { }; + +export function fnDeclHasUndefined(p: T | undefined = [], rParam: string): void { }; +export function fnDeclBad(p: T = [], rParam: string): void { }; + +export const fnExprOk1 = function (array: number[] = [], rParam: string): void { }; +export const fnExprOk2 = function (array: T | undefined = [], rParam: string): void { }; +export const fnExprBad = function (array: T = [], rParam: string): void { }; + +export const arrowOk1 = (array: number[] = [], rParam: string): void => { }; +export const arrowOk2 = (array: T | undefined = [], rParam: string): void => { }; +export const arrowBad = (array: T = [], rParam: string): void => { }; + +export const inObjectLiteralFnExprOk1 = { o: function (array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralFnExprOk2 = { o: function (array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralFnExprBad = { o: function (array: T = [], rParam: string): void { } }; + +export const inObjectLiteralArrowOk1 = { o: (array: number[] = [], rParam: string): void => { } }; +export const inObjectLiteralArrowOk2 = { o: (array: T | undefined = [], rParam: string): void => { } }; +export const inObjectLiteralArrowBad = { o: (array: T = [], rParam: string): void => { } }; + +export const inObjectLiteralMethodOk1 = { o(array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralMethodOk2 = { o(array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralMethodBad = { o(array: T = [], rParam: string): void { } }; + + +export class InClassFnExprOk1 { o = function (array: number[] = [], rParam: string): void { } }; +export class InClassFnExprOk2 { o = function (array: T | undefined = [], rParam: string): void { } }; +export class InClassFnExprBad { o = function (array: T = [], rParam: string): void { } }; + +export class InClassArrowOk1 { o = (array: number[] = [], rParam: string): void => { } }; +export class InClassArrowOk2 { o = (array: T | undefined = [], rParam: string): void => { } }; +export class InClassArrowBad { o = (array: T = [], rParam: string): void => { } }; + +export class InClassMethodOk1 { o(array: number[] = [], rParam: string): void { } }; +export class InClassMethodOk2 { o(array: T | undefined = [], rParam: string): void { } }; +export class InClassMethodBad { o(array: T = [], rParam: string): void { } }; + +//// [fnDecl.js] //// +export function fnDeclBasic1(p = [], rParam) { } +; +export function fnDeclBasic2(p = () => null, rParam) { } +; +export function fnDeclBasic3(p = class { +}, rParam) { } +; +export function fnDeclBasic4(p = [[]], rParam) { } +; +export function fnDeclBasic5(p = { a: [] }, rParam) { } +; +export function fnDeclBasic6(p = "_", rParam) { } +; +export function fnDeclBasic7(p = [], rParam) { } +; +export function fnDeclBasic8(p = [], rParam) { } +; +export function fnDeclHasUndefined(p = [], rParam) { } +; +export function fnDeclBad(p = [], rParam) { } +; +export const fnExprOk1 = function (array = [], rParam) { }; +export const fnExprOk2 = function (array = [], rParam) { }; +export const fnExprBad = function (array = [], rParam) { }; +export const arrowOk1 = (array = [], rParam) => { }; +export const arrowOk2 = (array = [], rParam) => { }; +export const arrowBad = (array = [], rParam) => { }; +export const inObjectLiteralFnExprOk1 = { o: function (array = [], rParam) { } }; +export const inObjectLiteralFnExprOk2 = { o: function (array = [], rParam) { } }; +export const inObjectLiteralFnExprBad = { o: function (array = [], rParam) { } }; +export const inObjectLiteralArrowOk1 = { o: (array = [], rParam) => { } }; +export const inObjectLiteralArrowOk2 = { o: (array = [], rParam) => { } }; +export const inObjectLiteralArrowBad = { o: (array = [], rParam) => { } }; +export const inObjectLiteralMethodOk1 = { o(array = [], rParam) { } }; +export const inObjectLiteralMethodOk2 = { o(array = [], rParam) { } }; +export const inObjectLiteralMethodBad = { o(array = [], rParam) { } }; +export class InClassFnExprOk1 { + o = function (array = [], rParam) { }; +} +; +export class InClassFnExprOk2 { + o = function (array = [], rParam) { }; +} +; +export class InClassFnExprBad { + o = function (array = [], rParam) { }; +} +; +export class InClassArrowOk1 { + o = (array = [], rParam) => { }; +} +; +export class InClassArrowOk2 { + o = (array = [], rParam) => { }; +} +; +export class InClassArrowBad { + o = (array = [], rParam) => { }; +} +; +export class InClassMethodOk1 { + o(array = [], rParam) { } +} +; +export class InClassMethodOk2 { + o(array = [], rParam) { } +} +; +export class InClassMethodBad { + o(array = [], rParam) { } +} +; diff --git a/tests/cases/compiler/isolatedDeclarationsAddUndefined.ts b/tests/cases/compiler/isolatedDeclarationsAddUndefined.ts index 95fa1f0a7e6..e8c49513096 100644 --- a/tests/cases/compiler/isolatedDeclarationsAddUndefined.ts +++ b/tests/cases/compiler/isolatedDeclarationsAddUndefined.ts @@ -15,6 +15,8 @@ export class Bar { export function foo(p = (ip = 10, v: number): void => {}): void{ } +type T = number +export function foo2(p = (ip = 10 as T, v: number): void => {}): void{} export class Bar2 { readonly r = 1; f = 2; diff --git a/tests/cases/transpile/declarationFunctionDeclarations.ts b/tests/cases/transpile/declarationFunctionDeclarations.ts new file mode 100644 index 00000000000..5aa0c50d4f8 --- /dev/null +++ b/tests/cases/transpile/declarationFunctionDeclarations.ts @@ -0,0 +1,51 @@ +// @declaration: true +// @target: esnext +// @strict: true + +//@fileName: fnDecl.ts +type T = number[] +export function fnDeclBasic1(p: number[] | string[] | [T] = [], rParam: string): void { }; +export function fnDeclBasic2(p: (n: T) => T = () => null!, rParam: string): void { }; +export function fnDeclBasic3(p: new () => any = class {}, rParam: string): void { }; +export function fnDeclBasic4(p: [T] = [[]], rParam: string): void { }; +export function fnDeclBasic5(p: { a: T } = { a: [] }, rParam: string): void { }; +export function fnDeclBasic6(p: `_${string}` = "_", rParam: string): void { }; +export function fnDeclBasic7(p: { a?: string } & number[] = [], rParam: string): void { }; +export function fnDeclBasic8(p: (number[] | string[]) | number = [], rParam: string): void { }; + +export function fnDeclHasUndefined(p: T | undefined = [], rParam: string): void { }; +export function fnDeclBad(p: T = [], rParam: string): void { }; + +export const fnExprOk1 = function (array: number[] = [], rParam: string): void { }; +export const fnExprOk2 = function (array: T | undefined = [], rParam: string): void { }; +export const fnExprBad = function (array: T = [], rParam: string): void { }; + +export const arrowOk1 = (array: number[] = [], rParam: string): void => { }; +export const arrowOk2 = (array: T | undefined = [], rParam: string): void => { }; +export const arrowBad = (array: T = [], rParam: string): void => { }; + +export const inObjectLiteralFnExprOk1 = { o: function (array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralFnExprOk2 = { o: function (array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralFnExprBad = { o: function (array: T = [], rParam: string): void { } }; + +export const inObjectLiteralArrowOk1 = { o: (array: number[] = [], rParam: string): void => { } }; +export const inObjectLiteralArrowOk2 = { o: (array: T | undefined = [], rParam: string): void => { } }; +export const inObjectLiteralArrowBad = { o: (array: T = [], rParam: string): void => { } }; + +export const inObjectLiteralMethodOk1 = { o(array: number[] = [], rParam: string): void { } }; +export const inObjectLiteralMethodOk2 = { o(array: T | undefined = [], rParam: string): void { } }; +export const inObjectLiteralMethodBad = { o(array: T = [], rParam: string): void { } }; + + +export class InClassFnExprOk1 { o = function (array: number[] = [], rParam: string): void { } }; +export class InClassFnExprOk2 { o = function (array: T | undefined = [], rParam: string): void { } }; +export class InClassFnExprBad { o = function (array: T = [], rParam: string): void { } }; + +export class InClassArrowOk1 { o = (array: number[] = [], rParam: string): void => { } }; +export class InClassArrowOk2 { o = (array: T | undefined = [], rParam: string): void => { } }; +export class InClassArrowBad { o = (array: T = [], rParam: string): void => { } }; + +export class InClassMethodOk1 { o(array: number[] = [], rParam: string): void { } }; +export class InClassMethodOk2 { o(array: T | undefined = [], rParam: string): void { } }; +export class InClassMethodBad { o(array: T = [], rParam: string): void { } }; +