Skip to content

Commit 667329d

Browse files
committed
Allow partial union props to contain the undefined type
1 parent b3f9bc0 commit 667329d

File tree

5 files changed

+117
-1
lines changed

5 files changed

+117
-1
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13201,7 +13201,8 @@ namespace ts {
1320113201
}
1320213202
return Ternary.False;
1320313203
}
13204-
const related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
13204+
// If the target comes from a partial union prop, allow `undefined` in the target type
13205+
const related = isRelatedTo(getTypeOfSymbol(sourceProp), addOptionality(getTypeOfSymbol(targetProp), !!(getCheckFlags(targetProp) & CheckFlags.Partial)), reportErrors);
1320513206
if (!related) {
1320613207
if (reportErrors) {
1320713208
reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [unionExcessPropsWithPartialMember.ts]
2+
interface A {
3+
unused?: string;
4+
x: string;
5+
}
6+
7+
interface B {
8+
x: string;
9+
y: string;
10+
}
11+
12+
declare var ab: A | B;
13+
declare var a: A;
14+
15+
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
16+
17+
18+
//// [unionExcessPropsWithPartialMember.js]
19+
"use strict";
20+
var __assign = (this && this.__assign) || function () {
21+
__assign = Object.assign || function(t) {
22+
for (var s, i = 1, n = arguments.length; i < n; i++) {
23+
s = arguments[i];
24+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
25+
t[p] = s[p];
26+
}
27+
return t;
28+
};
29+
return __assign.apply(this, arguments);
30+
};
31+
ab = __assign({}, a, { y: null }); // Should be allowed, since `y` is missing on `A`
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/compiler/unionExcessPropsWithPartialMember.ts ===
2+
interface A {
3+
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
4+
5+
unused?: string;
6+
>unused : Symbol(A.unused, Decl(unionExcessPropsWithPartialMember.ts, 0, 13))
7+
8+
x: string;
9+
>x : Symbol(A.x, Decl(unionExcessPropsWithPartialMember.ts, 1, 20))
10+
}
11+
12+
interface B {
13+
>B : Symbol(B, Decl(unionExcessPropsWithPartialMember.ts, 3, 1))
14+
15+
x: string;
16+
>x : Symbol(B.x, Decl(unionExcessPropsWithPartialMember.ts, 5, 13))
17+
18+
y: string;
19+
>y : Symbol(B.y, Decl(unionExcessPropsWithPartialMember.ts, 6, 14))
20+
}
21+
22+
declare var ab: A | B;
23+
>ab : Symbol(ab, Decl(unionExcessPropsWithPartialMember.ts, 10, 11))
24+
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
25+
>B : Symbol(B, Decl(unionExcessPropsWithPartialMember.ts, 3, 1))
26+
27+
declare var a: A;
28+
>a : Symbol(a, Decl(unionExcessPropsWithPartialMember.ts, 11, 11))
29+
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
30+
31+
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
32+
>ab : Symbol(ab, Decl(unionExcessPropsWithPartialMember.ts, 10, 11))
33+
>a : Symbol(a, Decl(unionExcessPropsWithPartialMember.ts, 11, 11))
34+
>y : Symbol(y, Decl(unionExcessPropsWithPartialMember.ts, 13, 11))
35+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/unionExcessPropsWithPartialMember.ts ===
2+
interface A {
3+
unused?: string;
4+
>unused : string | undefined
5+
6+
x: string;
7+
>x : string
8+
}
9+
10+
interface B {
11+
x: string;
12+
>x : string
13+
14+
y: string;
15+
>y : string
16+
}
17+
18+
declare var ab: A | B;
19+
>ab : A | B
20+
21+
declare var a: A;
22+
>a : A
23+
24+
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
25+
>ab = {...a, y: (null as any as string | undefined)} : { y: string | undefined; unused?: string | undefined; x: string; }
26+
>ab : A | B
27+
>{...a, y: (null as any as string | undefined)} : { y: string | undefined; unused?: string | undefined; x: string; }
28+
>a : A
29+
>y : string | undefined
30+
>(null as any as string | undefined) : string | undefined
31+
>null as any as string | undefined : string | undefined
32+
>null as any : any
33+
>null : null
34+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @strict: true
2+
interface A {
3+
unused?: string;
4+
x: string;
5+
}
6+
7+
interface B {
8+
x: string;
9+
y: string;
10+
}
11+
12+
declare var ab: A | B;
13+
declare var a: A;
14+
15+
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`

0 commit comments

Comments
 (0)