Skip to content

Commit 206bc9c

Browse files
authored
Types with extra properties are never subtypes of fresh object literals (#1759)
1 parent 458dd3b commit 206bc9c

File tree

4 files changed

+182
-7
lines changed

4 files changed

+182
-7
lines changed

internal/checker/relater.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4153,16 +4153,13 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b
41534153
}
41544154
return TernaryFalse
41554155
}
4156-
if isObjectLiteralType(target) {
4156+
if target.objectFlags&ObjectFlagsFreshLiteral != 0 {
41574157
for _, sourceProp := range excludeProperties(r.c.getPropertiesOfType(source), excludedProperties) {
41584158
if r.c.getPropertyOfObjectType(target, sourceProp.Name) == nil {
4159-
sourceType := r.c.getTypeOfSymbol(sourceProp)
4160-
if sourceType.flags&TypeFlagsUndefined == 0 {
4161-
if reportErrors {
4162-
r.reportError(diagnostics.Property_0_does_not_exist_on_type_1, r.c.symbolToString(sourceProp), r.c.TypeToString(target))
4163-
}
4164-
return TernaryFalse
4159+
if reportErrors {
4160+
r.reportError(diagnostics.Property_0_does_not_exist_on_type_1, r.c.symbolToString(sourceProp), r.c.TypeToString(target))
41654161
}
4162+
return TernaryFalse
41664163
}
41674164
}
41684165
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//// [tests/cases/compiler/freshObjectLiteralSubtype.ts] ////
2+
3+
=== freshObjectLiteralSubtype.ts ===
4+
function f1() {
5+
>f1 : Symbol(f1, Decl(freshObjectLiteralSubtype.ts, 0, 0))
6+
7+
if (!!true) {
8+
return { valid: true }
9+
>valid : Symbol(valid, Decl(freshObjectLiteralSubtype.ts, 2, 16))
10+
}
11+
return f2()
12+
>f2 : Symbol(f2, Decl(freshObjectLiteralSubtype.ts, 7, 13))
13+
}
14+
15+
declare const f2: () => { valid: boolean, msg?: undefined }
16+
>f2 : Symbol(f2, Decl(freshObjectLiteralSubtype.ts, 7, 13))
17+
>valid : Symbol(valid, Decl(freshObjectLiteralSubtype.ts, 7, 25))
18+
>msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 7, 41))
19+
20+
f1().msg
21+
>f1().msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 7, 41))
22+
>f1 : Symbol(f1, Decl(freshObjectLiteralSubtype.ts, 0, 0))
23+
>msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 7, 41))
24+
25+
// Repro from https://github.com/microsoft/typescript-go/issues/1742
26+
27+
function validate() {
28+
>validate : Symbol(validate, Decl(freshObjectLiteralSubtype.ts, 9, 8))
29+
30+
if(Math.random() > 0.5) {
31+
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
32+
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
33+
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
34+
35+
return utilValidate();
36+
>utilValidate : Symbol(utilValidate, Decl(freshObjectLiteralSubtype.ts, 18, 2))
37+
}
38+
return { valid: true };
39+
>valid : Symbol(valid, Decl(freshObjectLiteralSubtype.ts, 17, 12))
40+
41+
};
42+
43+
44+
declare function utilValidate(): {
45+
>utilValidate : Symbol(utilValidate, Decl(freshObjectLiteralSubtype.ts, 18, 2))
46+
47+
valid: boolean;
48+
>valid : Symbol(valid, Decl(freshObjectLiteralSubtype.ts, 21, 34))
49+
50+
msg?: undefined;
51+
>msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 22, 19))
52+
53+
} | {
54+
valid: boolean;
55+
>valid : Symbol(valid, Decl(freshObjectLiteralSubtype.ts, 24, 5))
56+
57+
msg: string;
58+
>msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 25, 19))
59+
}
60+
61+
validate().msg; // Error in TSGO
62+
>validate().msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 22, 19), Decl(freshObjectLiteralSubtype.ts, 25, 19))
63+
>validate : Symbol(validate, Decl(freshObjectLiteralSubtype.ts, 9, 8))
64+
>msg : Symbol(msg, Decl(freshObjectLiteralSubtype.ts, 22, 19), Decl(freshObjectLiteralSubtype.ts, 25, 19))
65+
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//// [tests/cases/compiler/freshObjectLiteralSubtype.ts] ////
2+
3+
=== freshObjectLiteralSubtype.ts ===
4+
function f1() {
5+
>f1 : () => { valid: boolean; msg?: undefined; }
6+
7+
if (!!true) {
8+
>!!true : true
9+
>!true : false
10+
>true : true
11+
12+
return { valid: true }
13+
>{ valid: true } : { valid: boolean; }
14+
>valid : boolean
15+
>true : true
16+
}
17+
return f2()
18+
>f2() : { valid: boolean; msg?: undefined; }
19+
>f2 : () => { valid: boolean; msg?: undefined; }
20+
}
21+
22+
declare const f2: () => { valid: boolean, msg?: undefined }
23+
>f2 : () => { valid: boolean; msg?: undefined; }
24+
>valid : boolean
25+
>msg : undefined
26+
27+
f1().msg
28+
>f1().msg : undefined
29+
>f1() : { valid: boolean; msg?: undefined; }
30+
>f1 : () => { valid: boolean; msg?: undefined; }
31+
>msg : undefined
32+
33+
// Repro from https://github.com/microsoft/typescript-go/issues/1742
34+
35+
function validate() {
36+
>validate : () => { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
37+
38+
if(Math.random() > 0.5) {
39+
>Math.random() > 0.5 : boolean
40+
>Math.random() : number
41+
>Math.random : () => number
42+
>Math : Math
43+
>random : () => number
44+
>0.5 : 0.5
45+
46+
return utilValidate();
47+
>utilValidate() : { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
48+
>utilValidate : () => { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
49+
}
50+
return { valid: true };
51+
>{ valid: true } : { valid: boolean; }
52+
>valid : boolean
53+
>true : true
54+
55+
};
56+
57+
58+
declare function utilValidate(): {
59+
>utilValidate : () => { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
60+
61+
valid: boolean;
62+
>valid : boolean
63+
64+
msg?: undefined;
65+
>msg : undefined
66+
67+
} | {
68+
valid: boolean;
69+
>valid : boolean
70+
71+
msg: string;
72+
>msg : string
73+
}
74+
75+
validate().msg; // Error in TSGO
76+
>validate().msg : string | undefined
77+
>validate() : { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
78+
>validate : () => { valid: boolean; msg?: undefined; } | { valid: boolean; msg: string; }
79+
>msg : string | undefined
80+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
function f1() {
5+
if (!!true) {
6+
return { valid: true }
7+
}
8+
return f2()
9+
}
10+
11+
declare const f2: () => { valid: boolean, msg?: undefined }
12+
13+
f1().msg
14+
15+
// Repro from https://github.com/microsoft/typescript-go/issues/1742
16+
17+
function validate() {
18+
if(Math.random() > 0.5) {
19+
return utilValidate();
20+
}
21+
return { valid: true };
22+
};
23+
24+
25+
declare function utilValidate(): {
26+
valid: boolean;
27+
msg?: undefined;
28+
} | {
29+
valid: boolean;
30+
msg: string;
31+
}
32+
33+
validate().msg; // Error in TSGO

0 commit comments

Comments
 (0)