diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4c74b60766b..6385d150a3e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14574,7 +14574,12 @@ namespace ts { priority |= InferencePriority.MappedTypeConstraint; inferFromTypes(getIndexType(source), constraintType); priority = savePriority; - inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(target)); + const valueTypes = compact([ + getIndexTypeOfType(source, IndexKind.String), + getIndexTypeOfType(source, IndexKind.Number), + ...map(getPropertiesOfType(source), getTypeOfSymbol) + ]); + inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(target)); return true; } return false; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index d4f5fe9664a..fd4807fc586 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -884,8 +884,11 @@ namespace ts { /** * Compacts an array, removing any falsey elements. */ - export function compact(array: T[]): T[]; - export function compact(array: ReadonlyArray): ReadonlyArray; + export function compact(array: (T | undefined | null | false | 0 | "")[]): T[]; + export function compact(array: ReadonlyArray): ReadonlyArray; + // 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 + export function compact(array: T[]): T[]; // tslint:disable-line unified-signatures + export function compact(array: ReadonlyArray): ReadonlyArray; // tslint:disable-line unified-signatures export function compact(array: T[]): T[] { let result: T[] | undefined; if (array) { diff --git a/tests/baselines/reference/mappedToToIndexSignatureInference.js b/tests/baselines/reference/mappedToToIndexSignatureInference.js new file mode 100644 index 00000000000..2ea09b663a9 --- /dev/null +++ b/tests/baselines/reference/mappedToToIndexSignatureInference.js @@ -0,0 +1,8 @@ +//// [mappedToToIndexSignatureInference.ts] +declare const fn: (object: { [Key in K]: V }) => object; +declare const a: { [index: string]: number }; +fn(a); + + +//// [mappedToToIndexSignatureInference.js] +fn(a); diff --git a/tests/baselines/reference/mappedToToIndexSignatureInference.symbols b/tests/baselines/reference/mappedToToIndexSignatureInference.symbols new file mode 100644 index 00000000000..d071f3f4c1c --- /dev/null +++ b/tests/baselines/reference/mappedToToIndexSignatureInference.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/mappedToToIndexSignatureInference.ts === +declare const fn: (object: { [Key in K]: V }) => object; +>fn : Symbol(fn, Decl(mappedToToIndexSignatureInference.ts, 0, 13)) +>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 0, 19)) +>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 0, 36)) +>object : Symbol(object, Decl(mappedToToIndexSignatureInference.ts, 0, 40)) +>Key : Symbol(Key, Decl(mappedToToIndexSignatureInference.ts, 0, 51)) +>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 0, 19)) +>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 0, 36)) + +declare const a: { [index: string]: number }; +>a : Symbol(a, Decl(mappedToToIndexSignatureInference.ts, 1, 13)) +>index : Symbol(index, Decl(mappedToToIndexSignatureInference.ts, 1, 20)) + +fn(a); +>fn : Symbol(fn, Decl(mappedToToIndexSignatureInference.ts, 0, 13)) +>a : Symbol(a, Decl(mappedToToIndexSignatureInference.ts, 1, 13)) + diff --git a/tests/baselines/reference/mappedToToIndexSignatureInference.types b/tests/baselines/reference/mappedToToIndexSignatureInference.types new file mode 100644 index 00000000000..35b9b3565e0 --- /dev/null +++ b/tests/baselines/reference/mappedToToIndexSignatureInference.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/mappedToToIndexSignatureInference.ts === +declare const fn: (object: { [Key in K]: V }) => object; +>fn : (object: { [Key in K]: V; }) => object +>object : { [Key in K]: V; } + +declare const a: { [index: string]: number }; +>a : { [index: string]: number; } +>index : string + +fn(a); +>fn(a) : object +>fn : (object: { [Key in K]: V; }) => object +>a : { [index: string]: number; } + diff --git a/tests/cases/compiler/mappedToToIndexSignatureInference.ts b/tests/cases/compiler/mappedToToIndexSignatureInference.ts new file mode 100644 index 00000000000..6ce63ead59c --- /dev/null +++ b/tests/cases/compiler/mappedToToIndexSignatureInference.ts @@ -0,0 +1,3 @@ +declare const fn: (object: { [Key in K]: V }) => object; +declare const a: { [index: string]: number }; +fn(a);