Skip to content

Commit 842cf17

Browse files
Improved errors for required parameters with default values in isolated declaration (microsoft#58637)
1 parent 6856735 commit 842cf17

10 files changed

+446
-21
lines changed

src/compiler/checker.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -6116,7 +6116,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61166116
return result;
61176117
}
61186118
}
6119-
context.tracker.reportInferenceFallback(existing);
61206119
return undefined;
61216120
}
61226121

@@ -8217,6 +8216,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
82178216
function serializeTypeForDeclaration(context: NodeBuilderContext, declaration: Declaration | undefined, type: Type, symbol: Symbol) {
82188217
const addUndefined = declaration && (isParameter(declaration) || isJSDocParameterTag(declaration)) && requiresAddingImplicitUndefined(declaration);
82198218
const enclosingDeclaration = context.enclosingDeclaration;
8219+
const oldFlags = context.flags;
8220+
if (declaration && hasInferredType(declaration) && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) {
8221+
syntacticNodeBuilder.serializeTypeOfDeclaration(declaration, context);
8222+
}
8223+
context.flags |= NodeBuilderFlags.NoSyntacticPrinter;
82208224
if (enclosingDeclaration && (!isErrorType(type) || (context.flags & NodeBuilderFlags.AllowUnresolvedNames))) {
82218225
const declWithExistingAnnotation = declaration && getNonlocalEffectiveTypeAnnotationNode(declaration)
82228226
? declaration
@@ -8226,11 +8230,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
82268230
const existing = getNonlocalEffectiveTypeAnnotationNode(declWithExistingAnnotation)!;
82278231
const result = !isTypePredicateNode(existing) && tryReuseExistingTypeNode(context, existing, type, declWithExistingAnnotation, addUndefined);
82288232
if (result) {
8233+
context.flags = oldFlags;
82298234
return result;
82308235
}
82318236
}
82328237
}
8233-
const oldFlags = context.flags;
82348238
if (
82358239
type.flags & TypeFlags.UniqueESSymbol &&
82368240
type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)))
@@ -8241,10 +8245,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
82418245
const decl = declaration ?? symbol.valueDeclaration ?? symbol.declarations?.[0];
82428246
const expr = decl && isDeclarationWithPossibleInnerTypeNodeReuse(decl) ? getPossibleTypeNodeReuseExpression(decl) : undefined;
82438247

8244-
if (decl && hasInferredType(decl) && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) {
8245-
syntacticNodeBuilder.serializeTypeOfDeclaration(decl, context);
8246-
}
8247-
context.flags |= NodeBuilderFlags.NoSyntacticPrinter;
82488248
const result = expressionOrTypeToTypeNode(context, expr, type, addUndefined);
82498249
context.flags = oldFlags;
82508250
return result;

src/compiler/expressionToTypeNode.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
isIdentifier,
3333
isJSDocTypeAssertion,
3434
isKeyword,
35-
isParameter,
3635
isPrimitiveLiteralValue,
3736
isShorthandPropertyAssignment,
3837
isSpreadAssignment,
@@ -76,8 +75,8 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
7675
serializeReturnTypeForSignature,
7776
serializeTypeOfExpression,
7877
};
79-
function serializeExistingTypeAnnotation(type: TypeNode | undefined) {
80-
return type === undefined ? undefined : !type.parent || !isParameter(type.parent) || !resolver.requiresAddingImplicitUndefined(type.parent) || canAddUndefined(type);
78+
function serializeExistingTypeAnnotation(type: TypeNode | undefined, addUndefined?: boolean) {
79+
return type !== undefined && (!addUndefined || (type && canAddUndefined(type))) ? true : undefined;
8180
}
8281
function serializeTypeOfExpression(expr: Expression, context: SyntacticTypeNodeBuilderContext, addUndefined?: boolean, preserveLiterals?: boolean) {
8382
return typeFromExpression(expr, context, /*isConstContext*/ false, addUndefined, preserveLiterals) ?? inferExpressionType(expr, context);
@@ -181,12 +180,12 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
181180
const declaredType = getEffectiveTypeAnnotationNode(node);
182181
const addUndefined = resolver.requiresAddingImplicitUndefined(node);
183182
let resultType;
184-
if (!addUndefined) {
185-
if (declaredType) {
186-
return serializeExistingTypeAnnotation(declaredType);
187-
}
183+
if (declaredType) {
184+
resultType = serializeExistingTypeAnnotation(declaredType, addUndefined);
185+
}
186+
else {
188187
if (node.initializer && isIdentifier(node.name)) {
189-
resultType = typeFromExpression(node.initializer, context);
188+
resultType = typeFromExpression(node.initializer, context, /*isConstContext*/ undefined, addUndefined);
190189
}
191190
}
192191
return resultType ?? inferTypeOfDeclaration(node, context);

tests/baselines/reference/isolatedDeclarationsAddUndefined.errors.txt

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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.
1+
file2.ts(4,38): error TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations.
22

33

44
==== file1.ts (0 errors) ====
@@ -12,10 +12,12 @@ file2.ts(1,26): error TS9025: Declaration emit for this parameter requires impli
1212

1313
==== file2.ts (1 errors) ====
1414
export function foo(p = (ip = 10, v: number): void => {}): void{
15-
~~~~~~~
16-
!!! error TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.
17-
!!! related TS9028 file2.ts:1:26: Add a type annotation to the parameter ip.
1815
}
16+
type T = number
17+
export function foo2(p = (ip = 10 as T, v: number): void => {}): void{}
18+
~
19+
!!! error TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations.
20+
!!! related TS9028 file2.ts:4:27: Add a type annotation to the parameter ip.
1921
export class Bar2 {
2022
readonly r = 1;
2123
f = 2;

tests/baselines/reference/isolatedDeclarationsAddUndefined.js

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export class Bar {
1212
//// [file2.ts]
1313
export function foo(p = (ip = 10, v: number): void => {}): void{
1414
}
15+
type T = number
16+
export function foo2(p = (ip = 10 as T, v: number): void => {}): void{}
1517
export class Bar2 {
1618
readonly r = 1;
1719
f = 2;
@@ -36,11 +38,17 @@ exports.Bar = Bar;
3638
Object.defineProperty(exports, "__esModule", { value: true });
3739
exports.Bar2 = void 0;
3840
exports.foo = foo;
41+
exports.foo2 = foo2;
3942
function foo(p) {
4043
if (p === void 0) { p = function (ip, v) {
4144
if (ip === void 0) { ip = 10; }
4245
}; }
4346
}
47+
function foo2(p) {
48+
if (p === void 0) { p = function (ip, v) {
49+
if (ip === void 0) { ip = 10; }
50+
}; }
51+
}
4452
var Bar2 = /** @class */ (function () {
4553
function Bar2() {
4654
this.r = 1;

tests/baselines/reference/isolatedDeclarationsAddUndefined.symbols

+13-3
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@ export function foo(p = (ip = 10, v: number): void => {}): void{
3030
>ip : Symbol(ip, Decl(file2.ts, 0, 25))
3131
>v : Symbol(v, Decl(file2.ts, 0, 33))
3232
}
33+
type T = number
34+
>T : Symbol(T, Decl(file2.ts, 1, 1))
35+
36+
export function foo2(p = (ip = 10 as T, v: number): void => {}): void{}
37+
>foo2 : Symbol(foo2, Decl(file2.ts, 2, 15))
38+
>p : Symbol(p, Decl(file2.ts, 3, 21))
39+
>ip : Symbol(ip, Decl(file2.ts, 3, 26))
40+
>T : Symbol(T, Decl(file2.ts, 1, 1))
41+
>v : Symbol(v, Decl(file2.ts, 3, 39))
42+
3343
export class Bar2 {
34-
>Bar2 : Symbol(Bar2, Decl(file2.ts, 1, 1))
44+
>Bar2 : Symbol(Bar2, Decl(file2.ts, 3, 71))
3545

3646
readonly r = 1;
37-
>r : Symbol(Bar2.r, Decl(file2.ts, 2, 19))
47+
>r : Symbol(Bar2.r, Decl(file2.ts, 4, 19))
3848

3949
f = 2;
40-
>f : Symbol(Bar2.f, Decl(file2.ts, 3, 19))
50+
>f : Symbol(Bar2.f, Decl(file2.ts, 5, 19))
4151
}

tests/baselines/reference/isolatedDeclarationsAddUndefined.types

+20
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,26 @@ export function foo(p = (ip = 10, v: number): void => {}): void{
5757
>v : number
5858
> : ^^^^^^
5959
}
60+
type T = number
61+
>T : number
62+
> : ^^^^^^
63+
64+
export function foo2(p = (ip = 10 as T, v: number): void => {}): void{}
65+
>foo2 : (p?: (ip: T | undefined, v: number) => void) => void
66+
> : ^ ^^^^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^
67+
>p : (ip: T | undefined, v: number) => void
68+
> : ^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^
69+
>(ip = 10 as T, v: number): void => {} : (ip: T | undefined, v: number) => void
70+
> : ^ ^^ ^^^^^^^^^^^^^^ ^^ ^^^^^
71+
>ip : number
72+
> : ^^^^^^
73+
>10 as T : number
74+
> : ^^^^^^
75+
>10 : 10
76+
> : ^^
77+
>v : number
78+
> : ^^^^^^
79+
6080
export class Bar2 {
6181
>Bar2 : Bar2
6282
> : ^^^^

0 commit comments

Comments
 (0)