Skip to content

Commit 568514f

Browse files
committed
tweak behavior of tuples with rest elements
1 parent 4a45c4c commit 568514f

5 files changed

+93
-21
lines changed

src/compiler/checker.ts

+6
Original file line numberDiff line numberDiff line change
@@ -13664,6 +13664,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1366413664

1366513665
function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) {
1366613666
if (isTupleType(type)) {
13667+
if (type.target.hasRestElement) {
13668+
// key of any rest/variadic element is number
13669+
// it subsumes all potential leading fixed elements
13670+
cb(numberType);
13671+
return
13672+
}
1366713673
forEachType(getUnionType(getElementTypes(type).map((_, i) => getStringLiteralType("" + i))), cb);
1366813674
return;
1366913675
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
mappedTypeTupleConstraintTypeParameterInNameType.ts(45,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'number'.
2+
Type 'string' is not assignable to type 'number'.
3+
mappedTypeTupleConstraintTypeParameterInNameType.ts(46,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'string'.
4+
Type 'number' is not assignable to type 'string'.
5+
mappedTypeTupleConstraintTypeParameterInNameType.ts(47,7): error TS2322: Type 'string | number | bigint' is not assignable to type 'bigint'.
6+
Type 'string' is not assignable to type 'bigint'.
7+
8+
9+
==== mappedTypeTupleConstraintTypeParameterInNameType.ts (3 errors) ====
10+
// based on https://github.com/microsoft/TypeScript/issues/55762
11+
12+
declare class Decoder<T> {
13+
decode(arrayBuffer: ArrayBuffer): T;
14+
}
15+
16+
type ValueTypeOf<T extends Decoder<any>> = T extends Decoder<infer R>
17+
? R
18+
: never;
19+
20+
type StructDescriptor = ReadonlyArray<
21+
readonly [key: string, type: Decoder<any>]
22+
>;
23+
24+
type StructTypeFor<Descriptor extends StructDescriptor> = {
25+
[K in keyof Descriptor as Descriptor[K][0]]: ValueTypeOf<Descriptor[K][1]>;
26+
};
27+
28+
class StructDecoder<const Descriptor extends StructDescriptor> extends Decoder<
29+
StructTypeFor<Descriptor>
30+
> {
31+
constructor(descriptor: Descriptor) {
32+
super();
33+
}
34+
}
35+
36+
declare const i32Decoder: Decoder<number>;
37+
declare const i64Decoder: Decoder<bigint>;
38+
39+
const structDecoder1 = new StructDecoder([
40+
["a", i32Decoder],
41+
["b", i64Decoder],
42+
]);
43+
44+
const struct1 = structDecoder1.decode(new ArrayBuffer(100));
45+
46+
const v1_1: number = struct1.a;
47+
const v1_2: bigint = struct1.b;
48+
49+
declare const descriptor2: [["a", Decoder<number>], ["b", Decoder<string>], ...["c", Decoder<bigint>][]]
50+
const structDecoder2 = new StructDecoder(descriptor2);
51+
52+
const struct2 = structDecoder2.decode(new ArrayBuffer(100));
53+
54+
const v2_1: number = struct2.a; // error, rest element expands to index signature access
55+
~~~~
56+
!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'number'.
57+
!!! error TS2322: Type 'string' is not assignable to type 'number'.
58+
const v2_2: string = struct2.b; // error, rest element expands to index signature access
59+
~~~~
60+
!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'string'.
61+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
62+
const v2_3: bigint = struct2.c; // error, rest element expands to index signature access
63+
~~~~
64+
!!! error TS2322: Type 'string | number | bigint' is not assignable to type 'bigint'.
65+
!!! error TS2322: Type 'string' is not assignable to type 'bigint'.
66+

tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols

+3-3
Original file line numberDiff line numberDiff line change
@@ -129,19 +129,19 @@ const struct2 = structDecoder2.decode(new ArrayBuffer(100));
129129
>decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26))
130130
>ArrayBuffer : Symbol(ArrayBuffer, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
131131

132-
const v2_1: number = struct2.a;
132+
const v2_1: number = struct2.a; // error, rest element expands to index signature access
133133
>v2_1 : Symbol(v2_1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 44, 5))
134134
>struct2.a : Symbol(a)
135135
>struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5))
136136
>a : Symbol(a)
137137

138-
const v2_2: string = struct2.b;
138+
const v2_2: string = struct2.b; // error, rest element expands to index signature access
139139
>v2_2 : Symbol(v2_2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 45, 5))
140140
>struct2.b : Symbol(b)
141141
>struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5))
142142
>b : Symbol(b)
143143

144-
const v2_3: bigint = struct2.c;
144+
const v2_3: bigint = struct2.c; // error, rest element expands to index signature access
145145
>v2_3 : Symbol(v2_3, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 46, 5))
146146
>struct2.c : Symbol(c)
147147
>struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5))

tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types

+15-15
Original file line numberDiff line numberDiff line change
@@ -161,33 +161,33 @@ const struct2 = structDecoder2.decode(new ArrayBuffer(100));
161161
>100 : 100
162162
> : ^^^
163163

164-
const v2_1: number = struct2.a;
164+
const v2_1: number = struct2.a; // error, rest element expands to index signature access
165165
>v2_1 : number
166166
> : ^^^^^^
167-
>struct2.a : number
168-
> : ^^^^^^
167+
>struct2.a : string | number | bigint
168+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
169169
>struct2 : StructTypeFor<[["a", Decoder<number>], ["b", Decoder<string>], ...["c", Decoder<bigint>][]]>
170170
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171-
>a : number
172-
> : ^^^^^^
171+
>a : string | number | bigint
172+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
173173

174-
const v2_2: string = struct2.b;
174+
const v2_2: string = struct2.b; // error, rest element expands to index signature access
175175
>v2_2 : string
176176
> : ^^^^^^
177-
>struct2.b : string
178-
> : ^^^^^^
177+
>struct2.b : string | number | bigint
178+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
179179
>struct2 : StructTypeFor<[["a", Decoder<number>], ["b", Decoder<string>], ...["c", Decoder<bigint>][]]>
180180
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
181-
>b : string
182-
> : ^^^^^^
181+
>b : string | number | bigint
182+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
183183

184-
const v2_3: bigint = struct2.c;
184+
const v2_3: bigint = struct2.c; // error, rest element expands to index signature access
185185
>v2_3 : bigint
186186
> : ^^^^^^
187-
>struct2.c : bigint
188-
> : ^^^^^^
187+
>struct2.c : string | number | bigint
188+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
189189
>struct2 : StructTypeFor<[["a", Decoder<number>], ["b", Decoder<string>], ...["c", Decoder<bigint>][]]>
190190
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
191-
>c : bigint
192-
> : ^^^^^^
191+
>c : string | number | bigint
192+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
193193

tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ const structDecoder2 = new StructDecoder(descriptor2);
4545

4646
const struct2 = structDecoder2.decode(new ArrayBuffer(100));
4747

48-
const v2_1: number = struct2.a;
49-
const v2_2: string = struct2.b;
50-
const v2_3: bigint = struct2.c;
48+
const v2_1: number = struct2.a; // error, rest element expands to index signature access
49+
const v2_2: string = struct2.b; // error, rest element expands to index signature access
50+
const v2_3: bigint = struct2.c; // error, rest element expands to index signature access

0 commit comments

Comments
 (0)