Skip to content

Commit d050673

Browse files
authored
elaborate check before converting fresh literal type to regular (microsoft#12595)
1 parent a33e653 commit d050673

File tree

4 files changed

+84
-1
lines changed

4 files changed

+84
-1
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7211,6 +7211,25 @@ namespace ts {
72117211
}
72127212
}
72137213

7214+
function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
7215+
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
7216+
return false;
7217+
}
7218+
// at this point we know that this is union or intersection type possibly with nullable constituents.
7219+
// check if we still will have compound type if we ignore nullable components.
7220+
let seenNonNullable = false;
7221+
for (const t of (<UnionOrIntersectionType>type).types) {
7222+
if (t.flags & TypeFlags.Nullable) {
7223+
continue;
7224+
}
7225+
if (seenNonNullable) {
7226+
return true;
7227+
}
7228+
seenNonNullable = true;
7229+
}
7230+
return false;
7231+
}
7232+
72147233
// Compare two types and return
72157234
// Ternary.True if they are related with no assumptions,
72167235
// Ternary.Maybe if they are related with assumptions of other relationships, or
@@ -7243,7 +7262,7 @@ namespace ts {
72437262
// and intersection types are further deconstructed on the target side, we don't want to
72447263
// make the check again (as it might fail for a partial target type). Therefore we obtain
72457264
// the regular source type and proceed with that.
7246-
if (target.flags & TypeFlags.UnionOrIntersection) {
7265+
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target)) {
72477266
source = getRegularTypeOfObjectLiteral(source);
72487267
}
72497268
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ nested: { prop: { colour: string; }; }; }' is not assignable to type 'NestedCSSProps'.
2+
Types of property 'nested' are incompatible.
3+
Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector | undefined'.
4+
Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
5+
Types of property 'prop' are incompatible.
6+
Type '{ colour: string; }' is not assignable to type 'CSSProps'.
7+
Object literal may only specify known properties, and 'colour' does not exist in type 'CSSProps'.
8+
9+
10+
==== tests/cases/compiler/nestedFreshLiteral.ts (1 errors) ====
11+
interface CSSProps {
12+
color?: string
13+
}
14+
interface NestedCSSProps {
15+
nested?: NestedSelector
16+
}
17+
interface NestedSelector {
18+
prop: CSSProps;
19+
}
20+
21+
let stylen: NestedCSSProps = {
22+
nested: { prop: { colour: 'red' } }
23+
~~~~~~~~~~~~~
24+
!!! error TS2322: Type '{ nested: { prop: { colour: string; }; }; }' is not assignable to type 'NestedCSSProps'.
25+
!!! error TS2322: Types of property 'nested' are incompatible.
26+
!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector | undefined'.
27+
!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
28+
!!! error TS2322: Types of property 'prop' are incompatible.
29+
!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'.
30+
!!! error TS2322: Object literal may only specify known properties, and 'colour' does not exist in type 'CSSProps'.
31+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [nestedFreshLiteral.ts]
2+
interface CSSProps {
3+
color?: string
4+
}
5+
interface NestedCSSProps {
6+
nested?: NestedSelector
7+
}
8+
interface NestedSelector {
9+
prop: CSSProps;
10+
}
11+
12+
let stylen: NestedCSSProps = {
13+
nested: { prop: { colour: 'red' } }
14+
}
15+
16+
//// [nestedFreshLiteral.js]
17+
var stylen = {
18+
nested: { prop: { colour: 'red' } }
19+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @strictNullChecks: true
2+
interface CSSProps {
3+
color?: string
4+
}
5+
interface NestedCSSProps {
6+
nested?: NestedSelector
7+
}
8+
interface NestedSelector {
9+
prop: CSSProps;
10+
}
11+
12+
let stylen: NestedCSSProps = {
13+
nested: { prop: { colour: 'red' } }
14+
}

0 commit comments

Comments
 (0)