diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index deb3afb1482bf..72aab03a94d11 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13664,6 +13664,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) { if (isTupleType(type)) { + if (type.target.hasRestElement) { + // key of any rest/variadic element is number + // it subsumes all potential leading fixed elements + cb(numberType); + return + } forEachType(getUnionType(getElementTypes(type).map((_, i) => getStringLiteralType("" + i))), cb); return; } diff --git a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.errors.txt b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.errors.txt new file mode 100644 index 0000000000000..e249a96e0b812 --- /dev/null +++ b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.errors.txt @@ -0,0 +1,66 @@ +mappedTypeTupleConstraintTypeParameterInNameType.ts(45,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +mappedTypeTupleConstraintTypeParameterInNameType.ts(46,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +mappedTypeTupleConstraintTypeParameterInNameType.ts(47,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'bigint'. + Type 'string' is not assignable to type 'bigint'. + + +==== mappedTypeTupleConstraintTypeParameterInNameType.ts (3 errors) ==== + // based on https://github.com/microsoft/TypeScript/issues/55762 + + declare class Decoder { + decode(arrayBuffer: ArrayBuffer): T; + } + + type ValueTypeOf> = T extends Decoder + ? R + : never; + + type StructDescriptor = ReadonlyArray< + readonly [key: string, type: Decoder] + >; + + type StructTypeFor = { + [K in keyof Descriptor as Descriptor[K][0]]: ValueTypeOf; + }; + + class StructDecoder extends Decoder< + StructTypeFor + > { + constructor(descriptor: Descriptor) { + super(); + } + } + + declare const i32Decoder: Decoder; + declare const i64Decoder: Decoder; + + const structDecoder1 = new StructDecoder([ + ["a", i32Decoder], + ["b", i64Decoder], + ]); + + const struct1 = structDecoder1.decode(new ArrayBuffer(100)); + + const v1_1: number = struct1.a; + const v1_2: bigint = struct1.b; + + declare const descriptor2: [["a", Decoder], ["b", Decoder], ...["c", Decoder][]] + const structDecoder2 = new StructDecoder(descriptor2); + + const struct2 = structDecoder2.decode(new ArrayBuffer(100)); + + const v2_1: number = struct2.a; // error, rest element expands to index signature access + ~~~~ +!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + const v2_2: string = struct2.b; // error, rest element expands to index signature access + ~~~~ +!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + const v2_3: bigint = struct2.c; // error, rest element expands to index signature access + ~~~~ +!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'bigint'. +!!! error TS2322: Type 'string' is not assignable to type 'bigint'. + \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols index 90bfd9835c784..c6a0b03a3e7d3 100644 --- a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols +++ b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols @@ -129,19 +129,19 @@ const struct2 = structDecoder2.decode(new ArrayBuffer(100)); >decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26)) >ArrayBuffer : Symbol(ArrayBuffer, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) -const v2_1: number = struct2.a; +const v2_1: number = struct2.a; // error, rest element expands to index signature access >v2_1 : Symbol(v2_1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 44, 5)) >struct2.a : Symbol(a) >struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5)) >a : Symbol(a) -const v2_2: string = struct2.b; +const v2_2: string = struct2.b; // error, rest element expands to index signature access >v2_2 : Symbol(v2_2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 45, 5)) >struct2.b : Symbol(b) >struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5)) >b : Symbol(b) -const v2_3: bigint = struct2.c; +const v2_3: bigint = struct2.c; // error, rest element expands to index signature access >v2_3 : Symbol(v2_3, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 46, 5)) >struct2.c : Symbol(c) >struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5)) diff --git a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types index 9a1f4355c3095..33d52c1dc4962 100644 --- a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types +++ b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types @@ -161,33 +161,33 @@ const struct2 = structDecoder2.decode(new ArrayBuffer(100)); >100 : 100 > : ^^^ -const v2_1: number = struct2.a; +const v2_1: number = struct2.a; // error, rest element expands to index signature access >v2_1 : number > : ^^^^^^ ->struct2.a : number -> : ^^^^^^ +>struct2.a : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->a : number -> : ^^^^^^ +>a : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ -const v2_2: string = struct2.b; +const v2_2: string = struct2.b; // error, rest element expands to index signature access >v2_2 : string > : ^^^^^^ ->struct2.b : string -> : ^^^^^^ +>struct2.b : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->b : string -> : ^^^^^^ +>b : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ -const v2_3: bigint = struct2.c; +const v2_3: bigint = struct2.c; // error, rest element expands to index signature access >v2_3 : bigint > : ^^^^^^ ->struct2.c : bigint -> : ^^^^^^ +>struct2.c : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->c : bigint -> : ^^^^^^ +>c : string | number | bigint +> : ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts b/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts index bacdd06a46743..bde1b5f007548 100644 --- a/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts +++ b/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts @@ -45,6 +45,6 @@ const structDecoder2 = new StructDecoder(descriptor2); const struct2 = structDecoder2.decode(new ArrayBuffer(100)); -const v2_1: number = struct2.a; -const v2_2: string = struct2.b; -const v2_3: bigint = struct2.c; +const v2_1: number = struct2.a; // error, rest element expands to index signature access +const v2_2: string = struct2.b; // error, rest element expands to index signature access +const v2_3: bigint = struct2.c; // error, rest element expands to index signature access