diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1262879ba3b2..7628eaaddd336 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18948,10 +18948,18 @@ namespace ts { return indexTypesIdenticalTo(source, target, kind); } const targetType = getIndexTypeOfType(target, kind); - if (!targetType || targetType.flags & TypeFlags.Any && !sourceIsPrimitive && kind === IndexKind.String) { - // Index signature of type any permits assignment from everything but primitives + if (!targetType) { return Ternary.True; } + if (targetType.flags & TypeFlags.Any && !sourceIsPrimitive) { + // An index signature of type `any` permits assignment from everything but primitives, + // provided that there is also a `string` index signature of type `any`. + const stringIndexType = kind === IndexKind.String ? targetType : getIndexTypeOfType(target, IndexKind.String); + if (stringIndexType && stringIndexType.flags & TypeFlags.Any) { + return Ternary.True; + } + + } if (isGenericMappedType(source)) { // A generic mapped type { [P in K]: T } is related to a type with an index signature // { [x: string]: U }, and optionally with an index signature { [x: number]: V }, diff --git a/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.errors.txt b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.errors.txt new file mode 100644 index 0000000000000..20362a25942c1 --- /dev/null +++ b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.errors.txt @@ -0,0 +1,145 @@ +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(43,5): error TS2322: Type 'Obj' is not assignable to type 'NumberTo'. + Index signature is missing in type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(49,5): error TS2739: Type 'StringTo' is missing the following properties from type 'Obj': hello, world +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(50,5): error TS2739: Type 'NumberTo' is missing the following properties from type 'Obj': hello, world +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(51,5): error TS2739: Type 'StringAndNumberTo' is missing the following properties from type 'Obj': hello, world +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(61,5): error TS2322: Type 'Obj' is not assignable to type 'NumberTo'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(65,5): error TS2322: Type 'Obj' is not assignable to type 'StringTo & NumberTo'. + Type 'Obj' is not assignable to type 'NumberTo'. + Index signature is missing in type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(67,5): error TS2322: Type 'StringTo' is not assignable to type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(68,5): error TS2322: Type 'NumberTo' is not assignable to type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(69,5): error TS2739: Type 'StringTo & NumberTo' is missing the following properties from type 'Obj': hello, world +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(84,5): error TS2322: Type 'Obj' is not assignable to type 'NumberToNumber'. + Index signature is missing in type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(88,5): error TS2322: Type 'Obj' is not assignable to type 'StringToAnyNumberToNumber'. + Index signature is missing in type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(90,5): error TS2322: Type 'StringTo' is not assignable to type 'Obj'. +tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts(91,5): error TS2739: Type 'NumberTo' is missing the following properties from type 'Obj': hello, world + + +==== tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts (13 errors) ==== + // When checking compatibility between two types, + // TypeScript should not require an index signature if + // the target side index signature maps to `any` *and* + // the target side has *any* string index signature to `any`. + // + // So an index signature like in + // + // { [x: number]: any } + // + // is still required of a source type, but neither index signature in + // + // { [x: number]: any, [x: string]: any; } + // + // should be required; *however*, the number index signature in + // + // { [x: number]: number, [x: string]: any; } + // + // should always be required. + + interface StringTo { + [x: string]: T; + } + + interface NumberTo { + [x: number]: T; + } + + interface StringAndNumberTo extends StringTo, NumberTo { + } + + interface Obj { + hello: string; + world: number; + } + + function f1(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + ~~~~~~ +!!! error TS2322: Type 'Obj' is not assignable to type 'NumberTo'. +!!! error TS2322: Index signature is missing in type 'Obj'. + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + + someObj = sToAny; + ~~~~~~~ +!!! error TS2739: Type 'StringTo' is missing the following properties from type 'Obj': hello, world + someObj = nToAny; + ~~~~~~~ +!!! error TS2739: Type 'NumberTo' is missing the following properties from type 'Obj': hello, world + someObj = bothToAny; + ~~~~~~~ +!!! error TS2739: Type 'StringAndNumberTo' is missing the following properties from type 'Obj': hello, world + } + + function f2(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + ~~~~~~ +!!! error TS2322: Type 'Obj' is not assignable to type 'NumberTo'. + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + ~~~~~~~~~ +!!! error TS2322: Type 'Obj' is not assignable to type 'StringTo & NumberTo'. +!!! error TS2322: Type 'Obj' is not assignable to type 'NumberTo'. +!!! error TS2322: Index signature is missing in type 'Obj'. + + someObj = sToAny; + ~~~~~~~ +!!! error TS2322: Type 'StringTo' is not assignable to type 'Obj'. + someObj = nToAny; + ~~~~~~~ +!!! error TS2322: Type 'NumberTo' is not assignable to type 'Obj'. + someObj = bothToAny; + ~~~~~~~ +!!! error TS2739: Type 'StringTo & NumberTo' is missing the following properties from type 'Obj': hello, world + } + + type NumberToNumber = NumberTo; + + interface StringToAnyNumberToNumber extends StringTo, NumberToNumber { + } + + function f3(sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) { + sToAny = nToNumber; + sToAny = strToAnyNumToNum; + sToAny = someObj; + + nToNumber = sToAny; + nToNumber = strToAnyNumToNum; + nToNumber = someObj; + ~~~~~~~~~ +!!! error TS2322: Type 'Obj' is not assignable to type 'NumberToNumber'. +!!! error TS2322: Index signature is missing in type 'Obj'. + + strToAnyNumToNum = sToAny; + strToAnyNumToNum = nToNumber; + strToAnyNumToNum = someObj; + ~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'Obj' is not assignable to type 'StringToAnyNumberToNumber'. +!!! error TS2322: Index signature is missing in type 'Obj'. + + someObj = sToAny; + ~~~~~~~ +!!! error TS2322: Type 'StringTo' is not assignable to type 'Obj'. + someObj = nToNumber; + ~~~~~~~ +!!! error TS2739: Type 'NumberTo' is missing the following properties from type 'Obj': hello, world + someObj = someObj; + } \ No newline at end of file diff --git a/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.js b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.js new file mode 100644 index 0000000000000..17f3b6248fa59 --- /dev/null +++ b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.js @@ -0,0 +1,157 @@ +//// [objectTypeWithStringAndNumberIndexSignatureToAny.ts] +// When checking compatibility between two types, +// TypeScript should not require an index signature if +// the target side index signature maps to `any` *and* +// the target side has *any* string index signature to `any`. +// +// So an index signature like in +// +// { [x: number]: any } +// +// is still required of a source type, but neither index signature in +// +// { [x: number]: any, [x: string]: any; } +// +// should be required; *however*, the number index signature in +// +// { [x: number]: number, [x: string]: any; } +// +// should always be required. + +interface StringTo { + [x: string]: T; +} + +interface NumberTo { + [x: number]: T; +} + +interface StringAndNumberTo extends StringTo, NumberTo { +} + +interface Obj { + hello: string; + world: number; +} + +function f1(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} + +function f2(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} + +type NumberToNumber = NumberTo; + +interface StringToAnyNumberToNumber extends StringTo, NumberToNumber { +} + +function f3(sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) { + sToAny = nToNumber; + sToAny = strToAnyNumToNum; + sToAny = someObj; + + nToNumber = sToAny; + nToNumber = strToAnyNumToNum; + nToNumber = someObj; + + strToAnyNumToNum = sToAny; + strToAnyNumToNum = nToNumber; + strToAnyNumToNum = someObj; + + someObj = sToAny; + someObj = nToNumber; + someObj = someObj; +} + +//// [objectTypeWithStringAndNumberIndexSignatureToAny.js] +"use strict"; +// When checking compatibility between two types, +// TypeScript should not require an index signature if +// the target side index signature maps to `any` *and* +// the target side has *any* string index signature to `any`. +// +// So an index signature like in +// +// { [x: number]: any } +// +// is still required of a source type, but neither index signature in +// +// { [x: number]: any, [x: string]: any; } +// +// should be required; *however*, the number index signature in +// +// { [x: number]: number, [x: string]: any; } +// +// should always be required. +function f1(sToAny, nToAny, bothToAny, someObj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} +function f2(sToAny, nToAny, bothToAny, someObj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} +function f3(sToAny, nToNumber, strToAnyNumToNum, someObj) { + sToAny = nToNumber; + sToAny = strToAnyNumToNum; + sToAny = someObj; + nToNumber = sToAny; + nToNumber = strToAnyNumToNum; + nToNumber = someObj; + strToAnyNumToNum = sToAny; + strToAnyNumToNum = nToNumber; + strToAnyNumToNum = someObj; + someObj = sToAny; + someObj = nToNumber; + someObj = someObj; +} diff --git a/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.symbols b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.symbols new file mode 100644 index 0000000000000..43187b5380d30 --- /dev/null +++ b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.symbols @@ -0,0 +1,247 @@ +=== tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts === +// When checking compatibility between two types, +// TypeScript should not require an index signature if +// the target side index signature maps to `any` *and* +// the target side has *any* string index signature to `any`. +// +// So an index signature like in +// +// { [x: number]: any } +// +// is still required of a source type, but neither index signature in +// +// { [x: number]: any, [x: string]: any; } +// +// should be required; *however*, the number index signature in +// +// { [x: number]: number, [x: string]: any; } +// +// should always be required. + +interface StringTo { +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 19, 19)) + + [x: string]: T; +>x : Symbol(x, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 20, 5)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 19, 19)) +} + +interface NumberTo { +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 23, 19)) + + [x: number]: T; +>x : Symbol(x, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 24, 5)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 23, 19)) +} + +interface StringAndNumberTo extends StringTo, NumberTo { +>StringAndNumberTo : Symbol(StringAndNumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 25, 1)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 27, 28)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 27, 28)) +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) +>T : Symbol(T, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 27, 28)) +} + +interface Obj { +>Obj : Symbol(Obj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 28, 1)) + + hello: string; +>hello : Symbol(Obj.hello, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 30, 15)) + + world: number; +>world : Symbol(Obj.world, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 31, 18)) +} + +function f1(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) { +>f1 : Symbol(f1, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 33, 1)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) +>StringAndNumberTo : Symbol(StringAndNumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 25, 1)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) +>Obj : Symbol(Obj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 28, 1)) + + sToAny = nToAny; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) + + sToAny = bothToAny; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) + + sToAny = someObj; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) + + nToAny = sToAny; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) + + nToAny = bothToAny; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) + + nToAny = someObj; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) + + bothToAny = sToAny; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) + + bothToAny = nToAny; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) + + bothToAny = someObj; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) + + someObj = sToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 12)) + + someObj = nToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 34)) + + someObj = bothToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 92)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 35, 57)) +} + +function f2(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) { +>f2 : Symbol(f2, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 51, 1)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) +>Obj : Symbol(Obj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 28, 1)) + + sToAny = nToAny; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) + + sToAny = bothToAny; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) + + sToAny = someObj; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) + + nToAny = sToAny; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) + + nToAny = bothToAny; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) + + nToAny = someObj; +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) + + bothToAny = sToAny; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) + + bothToAny = nToAny; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) + + bothToAny = someObj; +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) + + someObj = sToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 12)) + + someObj = nToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) +>nToAny : Symbol(nToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 34)) + + someObj = bothToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 99)) +>bothToAny : Symbol(bothToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 53, 57)) +} + +type NumberToNumber = NumberTo; +>NumberToNumber : Symbol(NumberToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 69, 1)) +>NumberTo : Symbol(NumberTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 21, 1)) + +interface StringToAnyNumberToNumber extends StringTo, NumberToNumber { +>StringToAnyNumberToNumber : Symbol(StringToAnyNumberToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 71, 39)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>NumberToNumber : Symbol(NumberToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 69, 1)) +} + +function f3(sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) { +>f3 : Symbol(f3, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 74, 1)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) +>StringTo : Symbol(StringTo, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 0, 0)) +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) +>NumberToNumber : Symbol(NumberToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 69, 1)) +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) +>StringToAnyNumberToNumber : Symbol(StringToAnyNumberToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 71, 39)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) +>Obj : Symbol(Obj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 28, 1)) + + sToAny = nToNumber; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) + + sToAny = strToAnyNumToNum; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) + + sToAny = someObj; +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) + + nToNumber = sToAny; +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) + + nToNumber = strToAnyNumToNum; +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) + + nToNumber = someObj; +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) + + strToAnyNumToNum = sToAny; +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) + + strToAnyNumToNum = nToNumber; +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) + + strToAnyNumToNum = someObj; +>strToAnyNumToNum : Symbol(strToAnyNumToNum, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 61)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) + + someObj = sToAny; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) +>sToAny : Symbol(sToAny, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 12)) + + someObj = nToNumber; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) +>nToNumber : Symbol(nToNumber, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 34)) + + someObj = someObj; +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) +>someObj : Symbol(someObj, Decl(objectTypeWithStringAndNumberIndexSignatureToAny.ts, 76, 106)) +} diff --git a/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.types b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.types new file mode 100644 index 0000000000000..5c2efdc2bc007 --- /dev/null +++ b/tests/baselines/reference/objectTypeWithStringAndNumberIndexSignatureToAny.types @@ -0,0 +1,250 @@ +=== tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts === +// When checking compatibility between two types, +// TypeScript should not require an index signature if +// the target side index signature maps to `any` *and* +// the target side has *any* string index signature to `any`. +// +// So an index signature like in +// +// { [x: number]: any } +// +// is still required of a source type, but neither index signature in +// +// { [x: number]: any, [x: string]: any; } +// +// should be required; *however*, the number index signature in +// +// { [x: number]: number, [x: string]: any; } +// +// should always be required. + +interface StringTo { + [x: string]: T; +>x : string +} + +interface NumberTo { + [x: number]: T; +>x : number +} + +interface StringAndNumberTo extends StringTo, NumberTo { +} + +interface Obj { + hello: string; +>hello : string + + world: number; +>world : number +} + +function f1(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) { +>f1 : (sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) => void +>sToAny : StringTo +>nToAny : NumberTo +>bothToAny : StringAndNumberTo +>someObj : Obj + + sToAny = nToAny; +>sToAny = nToAny : NumberTo +>sToAny : StringTo +>nToAny : NumberTo + + sToAny = bothToAny; +>sToAny = bothToAny : StringAndNumberTo +>sToAny : StringTo +>bothToAny : StringAndNumberTo + + sToAny = someObj; +>sToAny = someObj : Obj +>sToAny : StringTo +>someObj : Obj + + nToAny = sToAny; +>nToAny = sToAny : StringTo +>nToAny : NumberTo +>sToAny : StringTo + + nToAny = bothToAny; +>nToAny = bothToAny : StringAndNumberTo +>nToAny : NumberTo +>bothToAny : StringAndNumberTo + + nToAny = someObj; +>nToAny = someObj : Obj +>nToAny : NumberTo +>someObj : Obj + + bothToAny = sToAny; +>bothToAny = sToAny : StringTo +>bothToAny : StringAndNumberTo +>sToAny : StringTo + + bothToAny = nToAny; +>bothToAny = nToAny : NumberTo +>bothToAny : StringAndNumberTo +>nToAny : NumberTo + + bothToAny = someObj; +>bothToAny = someObj : Obj +>bothToAny : StringAndNumberTo +>someObj : Obj + + someObj = sToAny; +>someObj = sToAny : StringTo +>someObj : Obj +>sToAny : StringTo + + someObj = nToAny; +>someObj = nToAny : NumberTo +>someObj : Obj +>nToAny : NumberTo + + someObj = bothToAny; +>someObj = bothToAny : StringAndNumberTo +>someObj : Obj +>bothToAny : StringAndNumberTo +} + +function f2(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) { +>f2 : (sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) => void +>sToAny : StringTo +>nToAny : NumberTo +>bothToAny : StringTo & NumberTo +>someObj : Obj + + sToAny = nToAny; +>sToAny = nToAny : NumberTo +>sToAny : StringTo +>nToAny : NumberTo + + sToAny = bothToAny; +>sToAny = bothToAny : StringTo & NumberTo +>sToAny : StringTo +>bothToAny : StringTo & NumberTo + + sToAny = someObj; +>sToAny = someObj : Obj +>sToAny : StringTo +>someObj : Obj + + nToAny = sToAny; +>nToAny = sToAny : StringTo +>nToAny : NumberTo +>sToAny : StringTo + + nToAny = bothToAny; +>nToAny = bothToAny : StringTo & NumberTo +>nToAny : NumberTo +>bothToAny : StringTo & NumberTo + + nToAny = someObj; +>nToAny = someObj : Obj +>nToAny : NumberTo +>someObj : Obj + + bothToAny = sToAny; +>bothToAny = sToAny : StringTo +>bothToAny : StringTo & NumberTo +>sToAny : StringTo + + bothToAny = nToAny; +>bothToAny = nToAny : NumberTo +>bothToAny : StringTo & NumberTo +>nToAny : NumberTo + + bothToAny = someObj; +>bothToAny = someObj : Obj +>bothToAny : StringTo & NumberTo +>someObj : Obj + + someObj = sToAny; +>someObj = sToAny : StringTo +>someObj : Obj +>sToAny : StringTo + + someObj = nToAny; +>someObj = nToAny : NumberTo +>someObj : Obj +>nToAny : NumberTo + + someObj = bothToAny; +>someObj = bothToAny : StringTo & NumberTo +>someObj : Obj +>bothToAny : StringTo & NumberTo +} + +type NumberToNumber = NumberTo; +>NumberToNumber : NumberToNumber + +interface StringToAnyNumberToNumber extends StringTo, NumberToNumber { +} + +function f3(sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) { +>f3 : (sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) => void +>sToAny : StringTo +>nToNumber : NumberToNumber +>strToAnyNumToNum : StringToAnyNumberToNumber +>someObj : Obj + + sToAny = nToNumber; +>sToAny = nToNumber : NumberToNumber +>sToAny : StringTo +>nToNumber : NumberToNumber + + sToAny = strToAnyNumToNum; +>sToAny = strToAnyNumToNum : StringToAnyNumberToNumber +>sToAny : StringTo +>strToAnyNumToNum : StringToAnyNumberToNumber + + sToAny = someObj; +>sToAny = someObj : Obj +>sToAny : StringTo +>someObj : Obj + + nToNumber = sToAny; +>nToNumber = sToAny : StringTo +>nToNumber : NumberToNumber +>sToAny : StringTo + + nToNumber = strToAnyNumToNum; +>nToNumber = strToAnyNumToNum : StringToAnyNumberToNumber +>nToNumber : NumberToNumber +>strToAnyNumToNum : StringToAnyNumberToNumber + + nToNumber = someObj; +>nToNumber = someObj : Obj +>nToNumber : NumberToNumber +>someObj : Obj + + strToAnyNumToNum = sToAny; +>strToAnyNumToNum = sToAny : StringTo +>strToAnyNumToNum : StringToAnyNumberToNumber +>sToAny : StringTo + + strToAnyNumToNum = nToNumber; +>strToAnyNumToNum = nToNumber : NumberToNumber +>strToAnyNumToNum : StringToAnyNumberToNumber +>nToNumber : NumberToNumber + + strToAnyNumToNum = someObj; +>strToAnyNumToNum = someObj : Obj +>strToAnyNumToNum : StringToAnyNumberToNumber +>someObj : Obj + + someObj = sToAny; +>someObj = sToAny : StringTo +>someObj : Obj +>sToAny : StringTo + + someObj = nToNumber; +>someObj = nToNumber : NumberToNumber +>someObj : Obj +>nToNumber : NumberToNumber + + someObj = someObj; +>someObj = someObj : Obj +>someObj : Obj +>someObj : Obj +} diff --git a/tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts b/tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts new file mode 100644 index 0000000000000..6eb9eca9657e5 --- /dev/null +++ b/tests/cases/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts @@ -0,0 +1,95 @@ +// @strict: true + +// When checking compatibility between two types, +// TypeScript should not require an index signature if +// the target side index signature maps to `any` *and* +// the target side has *any* string index signature to `any`. +// +// So an index signature like in +// +// { [x: number]: any } +// +// is still required of a source type, but neither index signature in +// +// { [x: number]: any, [x: string]: any; } +// +// should be required; *however*, the number index signature in +// +// { [x: number]: number, [x: string]: any; } +// +// should always be required. + +interface StringTo { + [x: string]: T; +} + +interface NumberTo { + [x: number]: T; +} + +interface StringAndNumberTo extends StringTo, NumberTo { +} + +interface Obj { + hello: string; + world: number; +} + +function f1(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringAndNumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} + +function f2(sToAny: StringTo, nToAny: NumberTo, bothToAny: StringTo & NumberTo, someObj: Obj) { + sToAny = nToAny; + sToAny = bothToAny; + sToAny = someObj; + + nToAny = sToAny; + nToAny = bothToAny; + nToAny = someObj; + + bothToAny = sToAny; + bothToAny = nToAny; + bothToAny = someObj; + + someObj = sToAny; + someObj = nToAny; + someObj = bothToAny; +} + +type NumberToNumber = NumberTo; + +interface StringToAnyNumberToNumber extends StringTo, NumberToNumber { +} + +function f3(sToAny: StringTo, nToNumber: NumberToNumber, strToAnyNumToNum: StringToAnyNumberToNumber, someObj: Obj) { + sToAny = nToNumber; + sToAny = strToAnyNumToNum; + sToAny = someObj; + + nToNumber = sToAny; + nToNumber = strToAnyNumToNum; + nToNumber = someObj; + + strToAnyNumToNum = sToAny; + strToAnyNumToNum = nToNumber; + strToAnyNumToNum = someObj; + + someObj = sToAny; + someObj = nToNumber; + someObj = someObj; +} \ No newline at end of file