Skip to content

Commit df523b3

Browse files
authored
Filter the type of a binding pattern to not include undefined is the pattern parent has an initializer (#37309)
1 parent e0f6ecd commit df523b3

5 files changed

+60
-0
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7164,6 +7164,10 @@ namespace ts {
71647164
if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
71657165
parentType = getNonNullableType(parentType);
71667166
}
7167+
// Filter `undefined` from the type we check against if the parent has an initializer (which handles the `undefined` case implicitly)
7168+
else if (strictNullChecks && pattern.parent.initializer) {
7169+
parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined);
7170+
}
71677171

71687172
let type: Type | undefined;
71697173
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [contextualTypeForInitalizedVariablesFiltersUndefined.ts]
2+
const fInferred = ({ a = 0 } = {}) => a;
3+
// const fInferred: ({ a }?: { a?: number; }) => number
4+
5+
const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a;
6+
7+
//// [contextualTypeForInitalizedVariablesFiltersUndefined.js]
8+
"use strict";
9+
var fInferred = function (_a) {
10+
var _b = (_a === void 0 ? {} : _a).a, a = _b === void 0 ? 0 : _b;
11+
return a;
12+
};
13+
// const fInferred: ({ a }?: { a?: number; }) => number
14+
var fAnnotated = function (_a) {
15+
var _b = (_a === void 0 ? {} : _a).a, a = _b === void 0 ? 0 : _b;
16+
return a;
17+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts ===
2+
const fInferred = ({ a = 0 } = {}) => a;
3+
>fInferred : Symbol(fInferred, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 0, 5))
4+
>a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 0, 20))
5+
>a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 0, 20))
6+
7+
// const fInferred: ({ a }?: { a?: number; }) => number
8+
9+
const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a;
10+
>fAnnotated : Symbol(fAnnotated, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 3, 5))
11+
>fInferred : Symbol(fInferred, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 0, 5))
12+
>a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 3, 39))
13+
>a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 3, 39))
14+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts ===
2+
const fInferred = ({ a = 0 } = {}) => a;
3+
>fInferred : ({ a }?: { a?: number | undefined; }) => number
4+
>({ a = 0 } = {}) => a : ({ a }?: { a?: number | undefined; }) => number
5+
>a : number
6+
>0 : 0
7+
>{} : { a?: number | undefined; }
8+
>a : number
9+
10+
// const fInferred: ({ a }?: { a?: number; }) => number
11+
12+
const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a;
13+
>fAnnotated : ({ a }?: { a?: number | undefined; }) => number
14+
>fInferred : ({ a }?: { a?: number | undefined; }) => number
15+
>({ a = 0 } = {}) => a : ({ a }?: { a?: number | undefined; } | undefined) => number
16+
>a : number
17+
>0 : 0
18+
>{} : {}
19+
>a : number
20+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// @strict: true
2+
const fInferred = ({ a = 0 } = {}) => a;
3+
// const fInferred: ({ a }?: { a?: number; }) => number
4+
5+
const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a;

0 commit comments

Comments
 (0)