Skip to content

Commit 409be37

Browse files
authored
Fix index signature assignability from optional properties in --exactOptionalPropertyTypes mode (#45185)
* Explicit undefined not assignable to non-undefined index signature in exactOptionalPropertyTypes mode * Add tests
1 parent 3bd5079 commit 409be37

File tree

6 files changed

+169
-3
lines changed

6 files changed

+169
-3
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19457,8 +19457,8 @@ namespace ts {
1945719457
continue;
1945819458
}
1945919459
if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), keyType)) {
19460-
const propType = getTypeOfSymbol(prop);
19461-
const type = propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional)
19460+
const propType = getNonMissingTypeOfSymbol(prop);
19461+
const type = exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional)
1946219462
? propType
1946319463
: getTypeWithFacts(propType, TypeFacts.NEUndefined);
1946419464
const related = isRelatedTo(type, targetInfo.type, reportErrors);

tests/baselines/reference/strictOptionalProperties1.errors.txt

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@ tests/cases/compiler/strictOptionalProperties1.ts(107,45): error TS2322: Type 'u
1919
tests/cases/compiler/strictOptionalProperties1.ts(107,56): error TS2322: Type 'undefined' is not assignable to type 'boolean'.
2020
tests/cases/compiler/strictOptionalProperties1.ts(111,31): error TS2322: Type 'undefined' is not assignable to type 'number'.
2121
tests/cases/compiler/strictOptionalProperties1.ts(119,5): error TS2411: Property 'bar' of type 'string | undefined' is not assignable to 'string' index type 'string'.
22+
tests/cases/compiler/strictOptionalProperties1.ts(192,1): error TS2322: Type '{ a: number; b: string | undefined; }' is not assignable to type '{ [x: string]: string | number; }'.
23+
Property 'b' is incompatible with index signature.
24+
Type 'string | undefined' is not assignable to type 'string | number'.
25+
Type 'undefined' is not assignable to type 'string | number'.
26+
tests/cases/compiler/strictOptionalProperties1.ts(193,1): error TS2322: Type '{ a: number; b?: string | undefined; }' is not assignable to type '{ [x: string]: string | number; }'.
27+
Property 'b' is incompatible with index signature.
28+
Type 'string | undefined' is not assignable to type 'string | number'.
2229

2330

24-
==== tests/cases/compiler/strictOptionalProperties1.ts (17 errors) ====
31+
==== tests/cases/compiler/strictOptionalProperties1.ts (19 errors) ====
2532
function f1(obj: { a?: string, b?: string | undefined }) {
2633
let a = obj.a; // string | undefined
2734
let b = obj.b; // string | undefined
@@ -242,4 +249,26 @@ tests/cases/compiler/strictOptionalProperties1.ts(119,5): error TS2411: Property
242249
}
243250

244251
declare function bb(input: number): void;
252+
253+
// Repro from #44437
254+
255+
declare var a: {[x: string]: number | string }
256+
declare var b: {a: number, b: string}
257+
declare var c: {a: number, b?: string}
258+
declare var d: {a: number, b: string | undefined }
259+
declare var e: {a: number, b?: string | undefined }
260+
261+
a = b;
262+
a = c;
263+
a = d; // Error
264+
~
265+
!!! error TS2322: Type '{ a: number; b: string | undefined; }' is not assignable to type '{ [x: string]: string | number; }'.
266+
!!! error TS2322: Property 'b' is incompatible with index signature.
267+
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string | number'.
268+
!!! error TS2322: Type 'undefined' is not assignable to type 'string | number'.
269+
a = e; // Error
270+
~
271+
!!! error TS2322: Type '{ a: number; b?: string | undefined; }' is not assignable to type '{ [x: string]: string | number; }'.
272+
!!! error TS2322: Property 'b' is incompatible with index signature.
273+
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string | number'.
245274

tests/baselines/reference/strictOptionalProperties1.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,19 @@ function aa(input: Bar): void {
179179
}
180180

181181
declare function bb(input: number): void;
182+
183+
// Repro from #44437
184+
185+
declare var a: {[x: string]: number | string }
186+
declare var b: {a: number, b: string}
187+
declare var c: {a: number, b?: string}
188+
declare var d: {a: number, b: string | undefined }
189+
declare var e: {a: number, b?: string | undefined }
190+
191+
a = b;
192+
a = c;
193+
a = d; // Error
194+
a = e; // Error
182195

183196

184197
//// [strictOptionalProperties1.js]
@@ -309,6 +322,10 @@ function aa(input) {
309322
var notUndefinedVal = expectNotUndefined(input.bar);
310323
bb(notUndefinedVal);
311324
}
325+
a = b;
326+
a = c;
327+
a = d; // Error
328+
a = e; // Error
312329

313330

314331
//// [strictOptionalProperties1.d.ts]
@@ -382,3 +399,22 @@ interface Bar {
382399
}
383400
declare function aa(input: Bar): void;
384401
declare function bb(input: number): void;
402+
declare var a: {
403+
[x: string]: number | string;
404+
};
405+
declare var b: {
406+
a: number;
407+
b: string;
408+
};
409+
declare var c: {
410+
a: number;
411+
b?: string;
412+
};
413+
declare var d: {
414+
a: number;
415+
b: string | undefined;
416+
};
417+
declare var e: {
418+
a: number;
419+
b?: string | undefined;
420+
};

tests/baselines/reference/strictOptionalProperties1.symbols

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,45 @@ declare function bb(input: number): void;
571571
>bb : Symbol(bb, Decl(strictOptionalProperties1.ts, 177, 1))
572572
>input : Symbol(input, Decl(strictOptionalProperties1.ts, 179, 20))
573573

574+
// Repro from #44437
575+
576+
declare var a: {[x: string]: number | string }
577+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 183, 11))
578+
>x : Symbol(x, Decl(strictOptionalProperties1.ts, 183, 17))
579+
580+
declare var b: {a: number, b: string}
581+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 184, 11))
582+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 184, 16))
583+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 184, 26))
584+
585+
declare var c: {a: number, b?: string}
586+
>c : Symbol(c, Decl(strictOptionalProperties1.ts, 185, 11))
587+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 185, 16))
588+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 185, 26))
589+
590+
declare var d: {a: number, b: string | undefined }
591+
>d : Symbol(d, Decl(strictOptionalProperties1.ts, 186, 11))
592+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 186, 16))
593+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 186, 26))
594+
595+
declare var e: {a: number, b?: string | undefined }
596+
>e : Symbol(e, Decl(strictOptionalProperties1.ts, 187, 11))
597+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 187, 16))
598+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 187, 26))
599+
600+
a = b;
601+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 183, 11))
602+
>b : Symbol(b, Decl(strictOptionalProperties1.ts, 184, 11))
603+
604+
a = c;
605+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 183, 11))
606+
>c : Symbol(c, Decl(strictOptionalProperties1.ts, 185, 11))
607+
608+
a = d; // Error
609+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 183, 11))
610+
>d : Symbol(d, Decl(strictOptionalProperties1.ts, 186, 11))
611+
612+
a = e; // Error
613+
>a : Symbol(a, Decl(strictOptionalProperties1.ts, 183, 11))
614+
>e : Symbol(e, Decl(strictOptionalProperties1.ts, 187, 11))
615+

tests/baselines/reference/strictOptionalProperties1.types

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,49 @@ declare function bb(input: number): void;
683683
>bb : (input: number) => void
684684
>input : number
685685

686+
// Repro from #44437
687+
688+
declare var a: {[x: string]: number | string }
689+
>a : { [x: string]: string | number; }
690+
>x : string
691+
692+
declare var b: {a: number, b: string}
693+
>b : { a: number; b: string; }
694+
>a : number
695+
>b : string
696+
697+
declare var c: {a: number, b?: string}
698+
>c : { a: number; b?: string; }
699+
>a : number
700+
>b : string | undefined
701+
702+
declare var d: {a: number, b: string | undefined }
703+
>d : { a: number; b: string | undefined; }
704+
>a : number
705+
>b : string | undefined
706+
707+
declare var e: {a: number, b?: string | undefined }
708+
>e : { a: number; b?: string | undefined; }
709+
>a : number
710+
>b : string | undefined
711+
712+
a = b;
713+
>a = b : { a: number; b: string; }
714+
>a : { [x: string]: string | number; }
715+
>b : { a: number; b: string; }
716+
717+
a = c;
718+
>a = c : { a: number; b?: string; }
719+
>a : { [x: string]: string | number; }
720+
>c : { a: number; b?: string; }
721+
722+
a = d; // Error
723+
>a = d : { a: number; b: string | undefined; }
724+
>a : { [x: string]: string | number; }
725+
>d : { a: number; b: string | undefined; }
726+
727+
a = e; // Error
728+
>a = e : { a: number; b?: string | undefined; }
729+
>a : { [x: string]: string | number; }
730+
>e : { a: number; b?: string | undefined; }
731+

tests/cases/compiler/strictOptionalProperties1.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,16 @@ function aa(input: Bar): void {
182182
}
183183

184184
declare function bb(input: number): void;
185+
186+
// Repro from #44437
187+
188+
declare var a: {[x: string]: number | string }
189+
declare var b: {a: number, b: string}
190+
declare var c: {a: number, b?: string}
191+
declare var d: {a: number, b: string | undefined }
192+
declare var e: {a: number, b?: string | undefined }
193+
194+
a = b;
195+
a = c;
196+
a = d; // Error
197+
a = e; // Error

0 commit comments

Comments
 (0)