Skip to content

Commit 4da9d8b

Browse files
authored
Include index signatures of the source in mapped type template target inferences (#29253)
1 parent 5f782bf commit 4da9d8b

File tree

6 files changed

+54
-3
lines changed

6 files changed

+54
-3
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14574,7 +14574,12 @@ namespace ts {
1457414574
priority |= InferencePriority.MappedTypeConstraint;
1457514575
inferFromTypes(getIndexType(source), constraintType);
1457614576
priority = savePriority;
14577-
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
14577+
const valueTypes = compact([
14578+
getIndexTypeOfType(source, IndexKind.String),
14579+
getIndexTypeOfType(source, IndexKind.Number),
14580+
...map(getPropertiesOfType(source), getTypeOfSymbol)
14581+
]);
14582+
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(<MappedType>target));
1457814583
return true;
1457914584
}
1458014585
return false;

src/compiler/core.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,8 +884,11 @@ namespace ts {
884884
/**
885885
* Compacts an array, removing any falsey elements.
886886
*/
887-
export function compact<T>(array: T[]): T[];
888-
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>;
887+
export function compact<T>(array: (T | undefined | null | false | 0 | "")[]): T[];
888+
export function compact<T>(array: ReadonlyArray<T | undefined | null | false | 0 | "">): ReadonlyArray<T>;
889+
// TSLint thinks these can be combined with the above - they cannot; they'd produce higher-priority inferences and prevent the falsey types from being stripped
890+
export function compact<T>(array: T[]): T[]; // tslint:disable-line unified-signatures
891+
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>; // tslint:disable-line unified-signatures
889892
export function compact<T>(array: T[]): T[] {
890893
let result: T[] | undefined;
891894
if (array) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//// [mappedToToIndexSignatureInference.ts]
2+
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
3+
declare const a: { [index: string]: number };
4+
fn(a);
5+
6+
7+
//// [mappedToToIndexSignatureInference.js]
8+
fn(a);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/mappedToToIndexSignatureInference.ts ===
2+
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
3+
>fn : Symbol(fn, Decl(mappedToToIndexSignatureInference.ts, 0, 13))
4+
>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 0, 19))
5+
>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 0, 36))
6+
>object : Symbol(object, Decl(mappedToToIndexSignatureInference.ts, 0, 40))
7+
>Key : Symbol(Key, Decl(mappedToToIndexSignatureInference.ts, 0, 51))
8+
>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 0, 19))
9+
>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 0, 36))
10+
11+
declare const a: { [index: string]: number };
12+
>a : Symbol(a, Decl(mappedToToIndexSignatureInference.ts, 1, 13))
13+
>index : Symbol(index, Decl(mappedToToIndexSignatureInference.ts, 1, 20))
14+
15+
fn(a);
16+
>fn : Symbol(fn, Decl(mappedToToIndexSignatureInference.ts, 0, 13))
17+
>a : Symbol(a, Decl(mappedToToIndexSignatureInference.ts, 1, 13))
18+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/mappedToToIndexSignatureInference.ts ===
2+
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
3+
>fn : <K extends string, V>(object: { [Key in K]: V; }) => object
4+
>object : { [Key in K]: V; }
5+
6+
declare const a: { [index: string]: number };
7+
>a : { [index: string]: number; }
8+
>index : string
9+
10+
fn(a);
11+
>fn(a) : object
12+
>fn : <K extends string, V>(object: { [Key in K]: V; }) => object
13+
>a : { [index: string]: number; }
14+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
2+
declare const a: { [index: string]: number };
3+
fn(a);

0 commit comments

Comments
 (0)