From 3f8707d04f99bc0ca5bca55e745de74cadb16885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 16 Jan 2024 19:59:00 +0100 Subject: [PATCH] Add numeric constraint to type parameter of mapped types with name type and array constraints (#55774) --- src/compiler/checker.ts | 12 +- ...phicTupleInstantiationNameTypeKeys.symbols | 36 +++ ...orphicTupleInstantiationNameTypeKeys.types | 20 ++ ...eConstraintTypeParameterInNameType.symbols | 149 +++++++++++++ ...pleConstraintTypeParameterInNameType.types | 129 +++++++++++ ...ithAsClauseAndLateBoundProperty.errors.txt | 6 +- ...pedTypeWithAsClauseAndLateBoundProperty.js | 2 +- ...peWithAsClauseAndLateBoundProperty.symbols | 3 +- ...TypeWithAsClauseAndLateBoundProperty.types | 8 +- ...thAsClauseAndLateBoundProperty2.errors.txt | 11 + ...edTypeWithAsClauseAndLateBoundProperty2.js | 207 +----------------- ...eWithAsClauseAndLateBoundProperty2.symbols | 3 +- ...ypeWithAsClauseAndLateBoundProperty2.types | 8 +- ...momorphicTupleInstantiationNameTypeKeys.ts | 13 ++ ...eTupleConstraintTypeParameterInNameType.ts | 50 +++++ ...pedTypeWithAsClauseAndLateBoundProperty.ts | 2 +- ...edTypeWithAsClauseAndLateBoundProperty2.ts | 2 +- 17 files changed, 437 insertions(+), 224 deletions(-) create mode 100644 tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.symbols create mode 100644 tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.types create mode 100644 tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols create mode 100644 tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types create mode 100644 tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt create mode 100644 tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts create mode 100644 tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2c33821bef206..7aa61f37a7c75 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13850,6 +13850,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) { + if (isTupleType(type)) { + forEachType(getUnionType(getElementTypes(type).map((_, i) => getStringLiteralType("" + i))), cb); + return; + } + if (isArrayType(type)) { + cb(numberType); + return; + } for (const prop of getPropertiesOfType(type)) { cb(getLiteralTypeFromProperty(prop, include)); } @@ -16242,8 +16250,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } // Given a homomorphic mapped type { [K in keyof T]: XXX }, where T is constrained to an array or tuple type, in the - // template type XXX, K has an added constraint of number | `${number}`. - else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && node === (parent as MappedTypeNode).type) { + // template type XXX, K has an added constraint of number | `${number}`. The same is added in the optional name type. + else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && (node === (parent as MappedTypeNode).type || node === (parent as MappedTypeNode).nameType)) { const mappedType = getTypeFromTypeNode(parent as TypeNode) as MappedType; if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) { const typeParameter = getHomomorphicTypeVariable(mappedType); diff --git a/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.symbols b/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.symbols new file mode 100644 index 0000000000000..a7f398bb7bb28 --- /dev/null +++ b/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.symbols @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts] //// + +=== mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts === +// https://github.com/microsoft/TypeScript/pull/55774#issuecomment-1813484949 + +type Mapper = { +>Mapper : Symbol(Mapper, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 2, 12)) + + [K in keyof T as K]: T[K] extends NonNullable ? T[K] : never; +>K : Symbol(K, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 3, 3)) +>T : Symbol(T, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 2, 12)) +>K : Symbol(K, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 3, 3)) +>T : Symbol(T, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 2, 12)) +>K : Symbol(K, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 3, 3)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 2, 12)) +>K : Symbol(K, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 3, 3)) +>T : Symbol(T, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 2, 12)) +>K : Symbol(K, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 3, 3)) + +}; + +type Mapped = Mapper<[1, 2]>; +>Mapped : Symbol(Mapped, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 4, 2)) +>Mapper : Symbol(Mapper, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 0, 0)) + +type Keys = keyof Mapper<[1, 2]>; +>Keys : Symbol(Keys, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 6, 29)) +>Mapper : Symbol(Mapper, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 0, 0)) + +type SomeType = Mapped[Keys]; // ok +>SomeType : Symbol(SomeType, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 7, 33)) +>Mapped : Symbol(Mapped, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 4, 2)) +>Keys : Symbol(Keys, Decl(mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts, 6, 29)) + diff --git a/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.types b/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.types new file mode 100644 index 0000000000000..314ee7c796ec8 --- /dev/null +++ b/tests/baselines/reference/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.types @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts] //// + +=== mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts === +// https://github.com/microsoft/TypeScript/pull/55774#issuecomment-1813484949 + +type Mapper = { +>Mapper : Mapper + + [K in keyof T as K]: T[K] extends NonNullable ? T[K] : never; +}; + +type Mapped = Mapper<[1, 2]>; +>Mapped : Mapper<[1, 2]> + +type Keys = keyof Mapper<[1, 2]>; +>Keys : "0" | "1" + +type SomeType = Mapped[Keys]; // ok +>SomeType : 2 | 1 + diff --git a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols new file mode 100644 index 0000000000000..90bfd9835c784 --- /dev/null +++ b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.symbols @@ -0,0 +1,149 @@ +//// [tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts] //// + +=== mappedTypeTupleConstraintTypeParameterInNameType.ts === +// based on https://github.com/microsoft/TypeScript/issues/55762 + +declare class Decoder { +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 22)) + + decode(arrayBuffer: ArrayBuffer): T; +>decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26)) +>arrayBuffer : Symbol(arrayBuffer, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 3, 9)) +>ArrayBuffer : Symbol(ArrayBuffer, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 22)) +} + +type ValueTypeOf> = T extends Decoder +>ValueTypeOf : Symbol(ValueTypeOf, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 4, 1)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 6, 17)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 6, 17)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) +>R : Symbol(R, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 6, 66)) + + ? R +>R : Symbol(R, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 6, 66)) + + : never; + +type StructDescriptor = ReadonlyArray< +>StructDescriptor : Symbol(StructDescriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 8, 10)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + + readonly [key: string, type: Decoder] +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + +>; + +type StructTypeFor = { +>StructTypeFor : Symbol(StructTypeFor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 12, 2)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 14, 19)) +>StructDescriptor : Symbol(StructDescriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 8, 10)) + + [K in keyof Descriptor as Descriptor[K][0]]: ValueTypeOf; +>K : Symbol(K, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 15, 3)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 14, 19)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 14, 19)) +>K : Symbol(K, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 15, 3)) +>ValueTypeOf : Symbol(ValueTypeOf, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 4, 1)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 14, 19)) +>K : Symbol(K, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 15, 3)) + +}; + +class StructDecoder extends Decoder< +>StructDecoder : Symbol(StructDecoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 16, 2)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 18, 20)) +>StructDescriptor : Symbol(StructDescriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 8, 10)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + + StructTypeFor +>StructTypeFor : Symbol(StructTypeFor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 12, 2)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 18, 20)) + +> { + constructor(descriptor: Descriptor) { +>descriptor : Symbol(descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 21, 14)) +>Descriptor : Symbol(Descriptor, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 18, 20)) + + super(); +>super : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + } +} + +declare const i32Decoder: Decoder; +>i32Decoder : Symbol(i32Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 26, 13)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + +declare const i64Decoder: Decoder; +>i64Decoder : Symbol(i64Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 27, 13)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + +const structDecoder1 = new StructDecoder([ +>structDecoder1 : Symbol(structDecoder1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 29, 5)) +>StructDecoder : Symbol(StructDecoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 16, 2)) + + ["a", i32Decoder], +>i32Decoder : Symbol(i32Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 26, 13)) + + ["b", i64Decoder], +>i64Decoder : Symbol(i64Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 27, 13)) + +]); + +const struct1 = structDecoder1.decode(new ArrayBuffer(100)); +>struct1 : Symbol(struct1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 34, 5)) +>structDecoder1.decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26)) +>structDecoder1 : Symbol(structDecoder1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 29, 5)) +>decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26)) +>ArrayBuffer : Symbol(ArrayBuffer, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +const v1_1: number = struct1.a; +>v1_1 : Symbol(v1_1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 36, 5)) +>struct1.a : Symbol(a) +>struct1 : Symbol(struct1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 34, 5)) +>a : Symbol(a) + +const v1_2: bigint = struct1.b; +>v1_2 : Symbol(v1_2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 37, 5)) +>struct1.b : Symbol(b) +>struct1 : Symbol(struct1, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 34, 5)) +>b : Symbol(b) + +declare const descriptor2: [["a", Decoder], ["b", Decoder], ...["c", Decoder][]] +>descriptor2 : Symbol(descriptor2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 39, 13)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) +>Decoder : Symbol(Decoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 0, 0)) + +const structDecoder2 = new StructDecoder(descriptor2); +>structDecoder2 : Symbol(structDecoder2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 40, 5)) +>StructDecoder : Symbol(StructDecoder, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 16, 2)) +>descriptor2 : Symbol(descriptor2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 39, 13)) + +const struct2 = structDecoder2.decode(new ArrayBuffer(100)); +>struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5)) +>structDecoder2.decode : Symbol(Decoder.decode, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 2, 26)) +>structDecoder2 : Symbol(structDecoder2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 40, 5)) +>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; +>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; +>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; +>v2_3 : Symbol(v2_3, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 46, 5)) +>struct2.c : Symbol(c) +>struct2 : Symbol(struct2, Decl(mappedTypeTupleConstraintTypeParameterInNameType.ts, 42, 5)) +>c : Symbol(c) + diff --git a/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types new file mode 100644 index 0000000000000..8b80020c7c791 --- /dev/null +++ b/tests/baselines/reference/mappedTypeTupleConstraintTypeParameterInNameType.types @@ -0,0 +1,129 @@ +//// [tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts] //// + +=== mappedTypeTupleConstraintTypeParameterInNameType.ts === +// based on https://github.com/microsoft/TypeScript/issues/55762 + +declare class Decoder { +>Decoder : Decoder + + decode(arrayBuffer: ArrayBuffer): T; +>decode : (arrayBuffer: ArrayBuffer) => T +>arrayBuffer : ArrayBuffer +} + +type ValueTypeOf> = T extends Decoder +>ValueTypeOf : ValueTypeOf + + ? R + : never; + +type StructDescriptor = ReadonlyArray< +>StructDescriptor : readonly (readonly [key: string, type: Decoder])[] + + readonly [key: string, type: Decoder] +>; + +type StructTypeFor = { +>StructTypeFor : StructTypeFor + + [K in keyof Descriptor as Descriptor[K][0]]: ValueTypeOf; +}; + +class StructDecoder extends Decoder< +>StructDecoder : StructDecoder +>Decoder : Decoder> + + StructTypeFor +> { + constructor(descriptor: Descriptor) { +>descriptor : Descriptor + + super(); +>super() : void +>super : typeof Decoder + } +} + +declare const i32Decoder: Decoder; +>i32Decoder : Decoder + +declare const i64Decoder: Decoder; +>i64Decoder : Decoder + +const structDecoder1 = new StructDecoder([ +>structDecoder1 : StructDecoder], readonly ["b", Decoder]]> +>new StructDecoder([ ["a", i32Decoder], ["b", i64Decoder],]) : StructDecoder], readonly ["b", Decoder]]> +>StructDecoder : typeof StructDecoder +>[ ["a", i32Decoder], ["b", i64Decoder],] : [["a", Decoder], ["b", Decoder]] + + ["a", i32Decoder], +>["a", i32Decoder] : ["a", Decoder] +>"a" : "a" +>i32Decoder : Decoder + + ["b", i64Decoder], +>["b", i64Decoder] : ["b", Decoder] +>"b" : "b" +>i64Decoder : Decoder + +]); + +const struct1 = structDecoder1.decode(new ArrayBuffer(100)); +>struct1 : StructTypeFor], readonly ["b", Decoder]]> +>structDecoder1.decode(new ArrayBuffer(100)) : StructTypeFor], readonly ["b", Decoder]]> +>structDecoder1.decode : (arrayBuffer: ArrayBuffer) => StructTypeFor], readonly ["b", Decoder]]> +>structDecoder1 : StructDecoder], readonly ["b", Decoder]]> +>decode : (arrayBuffer: ArrayBuffer) => StructTypeFor], readonly ["b", Decoder]]> +>new ArrayBuffer(100) : ArrayBuffer +>ArrayBuffer : ArrayBufferConstructor +>100 : 100 + +const v1_1: number = struct1.a; +>v1_1 : number +>struct1.a : number +>struct1 : StructTypeFor], readonly ["b", Decoder]]> +>a : number + +const v1_2: bigint = struct1.b; +>v1_2 : bigint +>struct1.b : bigint +>struct1 : StructTypeFor], readonly ["b", Decoder]]> +>b : bigint + +declare const descriptor2: [["a", Decoder], ["b", Decoder], ...["c", Decoder][]] +>descriptor2 : [["a", Decoder], ["b", Decoder], ...["c", Decoder][]] + +const structDecoder2 = new StructDecoder(descriptor2); +>structDecoder2 : StructDecoder<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>new StructDecoder(descriptor2) : StructDecoder<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>StructDecoder : typeof StructDecoder +>descriptor2 : [["a", Decoder], ["b", Decoder], ...["c", Decoder][]] + +const struct2 = structDecoder2.decode(new ArrayBuffer(100)); +>struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>structDecoder2.decode(new ArrayBuffer(100)) : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>structDecoder2.decode : (arrayBuffer: ArrayBuffer) => StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>structDecoder2 : StructDecoder<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>decode : (arrayBuffer: ArrayBuffer) => StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>new ArrayBuffer(100) : ArrayBuffer +>ArrayBuffer : ArrayBufferConstructor +>100 : 100 + +const v2_1: number = struct2.a; +>v2_1 : number +>struct2.a : number +>struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>a : number + +const v2_2: string = struct2.b; +>v2_2 : string +>struct2.b : string +>struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>b : string + +const v2_3: bigint = struct2.c; +>v2_3 : bigint +>struct2.c : bigint +>struct2 : StructTypeFor<[["a", Decoder], ["b", Decoder], ...["c", Decoder][]]> +>c : bigint + diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt index 6dac97e6c4f8e..a2f7f389e954d 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt @@ -1,11 +1,11 @@ -mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; }' but required in type 'number[]'. +mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error TS2741: Property 'length' is missing in type '{ [x: number]: number; [iterator]: () => IterableIterator; [unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; }' but required in type 'number[]'. ==== mappedTypeWithAsClauseAndLateBoundProperty.ts (1 errors) ==== declare let tgt2: number[]; - declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; + declare let src2: { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }; tgt2 = src2; // Should error ~~~~ -!!! error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; }' but required in type 'number[]'. +!!! error TS2741: Property 'length' is missing in type '{ [x: number]: number; [iterator]: () => IterableIterator; [unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; }' but required in type 'number[]'. !!! related TS2728 lib.es5.d.ts:--:--: 'length' is declared here. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.js b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.js index 48a71e30900be..63d34830e59b7 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.js +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.js @@ -2,7 +2,7 @@ //// [mappedTypeWithAsClauseAndLateBoundProperty.ts] declare let tgt2: number[]; -declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; +declare let src2: { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }; tgt2 = src2; // Should error diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.symbols b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.symbols index cb287cbc8618f..2479f338987f8 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.symbols +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.symbols @@ -4,9 +4,10 @@ declare let tgt2: number[]; >tgt2 : Symbol(tgt2, Decl(mappedTypeWithAsClauseAndLateBoundProperty.ts, 0, 11)) -declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; +declare let src2: { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }; >src2 : Symbol(src2, Decl(mappedTypeWithAsClauseAndLateBoundProperty.ts, 1, 11)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty.ts, 1, 21)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty.ts, 1, 21)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty.ts, 1, 21)) diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.types b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.types index 4d9bf2b86fb35..8ae10558c90ab 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.types +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.types @@ -4,11 +4,11 @@ declare let tgt2: number[]; >tgt2 : number[] -declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; ->src2 : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } +declare let src2: { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }; +>src2 : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } tgt2 = src2; // Should error ->tgt2 = src2 : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } +>tgt2 = src2 : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } >tgt2 : number[] ->src2 : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } +>src2 : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt new file mode 100644 index 0000000000000..2cf2dd1103d8c --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt @@ -0,0 +1,11 @@ +mappedTypeWithAsClauseAndLateBoundProperty2.ts(1,14): error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. +mappedTypeWithAsClauseAndLateBoundProperty2.ts(1,14): error TS4118: The type of this node cannot be serialized because its property '[unscopables]' cannot be serialized. + + +==== mappedTypeWithAsClauseAndLateBoundProperty2.ts (2 errors) ==== + export const thing = (null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }); + ~~~~~ +!!! error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. + ~~~~~ +!!! error TS4118: The type of this node cannot be serialized because its property '[unscopables]' cannot be serialized. + \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js index 9bfc37222f9a8..ed9292c50c53d 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js @@ -1,213 +1,8 @@ //// [tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts] //// //// [mappedTypeWithAsClauseAndLateBoundProperty2.ts] -export const thing = (null as any as { [K in keyof number[] as Exclude]: (number[])[K] }); +export const thing = (null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }); //// [mappedTypeWithAsClauseAndLateBoundProperty2.js] export const thing = null; - - -//// [mappedTypeWithAsClauseAndLateBoundProperty2.d.ts] -export declare const thing: { - [x: number]: number; - toString: () => string; - toLocaleString: () => string; - pop: () => number; - push: (...items: number[]) => number; - concat: { - (...items: ConcatArray[]): number[]; - (...items: (number | ConcatArray)[]): number[]; - }; - join: (separator?: string) => string; - reverse: () => number[]; - shift: () => number; - slice: (start?: number, end?: number) => number[]; - sort: (compareFn?: (a: number, b: number) => number) => number[]; - splice: { - (start: number, deleteCount?: number): number[]; - (start: number, deleteCount: number, ...items: number[]): number[]; - }; - unshift: (...items: number[]) => number; - indexOf: (searchElement: number, fromIndex?: number) => number; - lastIndexOf: (searchElement: number, fromIndex?: number) => number; - every: { - (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; - (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; - }; - some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; - forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; - map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; - filter: { - (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; - (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; - }; - reduce: { - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; - (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; - }; - reduceRight: { - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; - (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; - }; - find: { - (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; - (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; - }; - findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; - fill: (value: number, start?: number, end?: number) => number[]; - copyWithin: (target: number, start: number, end?: number) => number[]; - entries: () => IterableIterator<[number, number]>; - keys: () => IterableIterator; - values: () => IterableIterator; - includes: (searchElement: number, fromIndex?: number) => boolean; - flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; - flat: (this: A, depth?: D) => FlatArray[]; - [Symbol.iterator]: () => IterableIterator; - readonly [Symbol.unscopables]: { - [x: number]: boolean; - length?: boolean; - toString?: boolean; - toLocaleString?: boolean; - pop?: boolean; - push?: boolean; - concat?: boolean; - join?: boolean; - reverse?: boolean; - shift?: boolean; - slice?: boolean; - sort?: boolean; - splice?: boolean; - unshift?: boolean; - indexOf?: boolean; - lastIndexOf?: boolean; - every?: boolean; - some?: boolean; - forEach?: boolean; - map?: boolean; - filter?: boolean; - reduce?: boolean; - reduceRight?: boolean; - find?: boolean; - findIndex?: boolean; - fill?: boolean; - copyWithin?: boolean; - entries?: boolean; - keys?: boolean; - values?: boolean; - includes?: boolean; - flatMap?: boolean; - flat?: boolean; - [Symbol.iterator]?: boolean; - readonly [Symbol.unscopables]?: boolean; - }; -}; - - -//// [DtsFileErrors] - - -mappedTypeWithAsClauseAndLateBoundProperty2.d.ts(24,118): error TS2526: A 'this' type is available only in a non-static member of a class or interface. - - -==== mappedTypeWithAsClauseAndLateBoundProperty2.d.ts (1 errors) ==== - export declare const thing: { - [x: number]: number; - toString: () => string; - toLocaleString: () => string; - pop: () => number; - push: (...items: number[]) => number; - concat: { - (...items: ConcatArray[]): number[]; - (...items: (number | ConcatArray)[]): number[]; - }; - join: (separator?: string) => string; - reverse: () => number[]; - shift: () => number; - slice: (start?: number, end?: number) => number[]; - sort: (compareFn?: (a: number, b: number) => number) => number[]; - splice: { - (start: number, deleteCount?: number): number[]; - (start: number, deleteCount: number, ...items: number[]): number[]; - }; - unshift: (...items: number[]) => number; - indexOf: (searchElement: number, fromIndex?: number) => number; - lastIndexOf: (searchElement: number, fromIndex?: number) => number; - every: { - (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; - ~~~~ -!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. - (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; - }; - some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; - forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; - map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; - filter: { - (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; - (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; - }; - reduce: { - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; - (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; - }; - reduceRight: { - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; - (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; - (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; - }; - find: { - (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; - (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; - }; - findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; - fill: (value: number, start?: number, end?: number) => number[]; - copyWithin: (target: number, start: number, end?: number) => number[]; - entries: () => IterableIterator<[number, number]>; - keys: () => IterableIterator; - values: () => IterableIterator; - includes: (searchElement: number, fromIndex?: number) => boolean; - flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; - flat: (this: A, depth?: D) => FlatArray[]; - [Symbol.iterator]: () => IterableIterator; - readonly [Symbol.unscopables]: { - [x: number]: boolean; - length?: boolean; - toString?: boolean; - toLocaleString?: boolean; - pop?: boolean; - push?: boolean; - concat?: boolean; - join?: boolean; - reverse?: boolean; - shift?: boolean; - slice?: boolean; - sort?: boolean; - splice?: boolean; - unshift?: boolean; - indexOf?: boolean; - lastIndexOf?: boolean; - every?: boolean; - some?: boolean; - forEach?: boolean; - map?: boolean; - filter?: boolean; - reduce?: boolean; - reduceRight?: boolean; - find?: boolean; - findIndex?: boolean; - fill?: boolean; - copyWithin?: boolean; - entries?: boolean; - keys?: boolean; - values?: boolean; - includes?: boolean; - flatMap?: boolean; - flat?: boolean; - [Symbol.iterator]?: boolean; - readonly [Symbol.unscopables]?: boolean; - }; - }; - \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.symbols b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.symbols index e754e23b65a39..d4d6b078f6893 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.symbols +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.symbols @@ -1,9 +1,10 @@ //// [tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts] //// === mappedTypeWithAsClauseAndLateBoundProperty2.ts === -export const thing = (null as any as { [K in keyof number[] as Exclude]: (number[])[K] }); +export const thing = (null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }); >thing : Symbol(thing, Decl(mappedTypeWithAsClauseAndLateBoundProperty2.ts, 0, 12)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty2.ts, 0, 40)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty2.ts, 0, 40)) >K : Symbol(K, Decl(mappedTypeWithAsClauseAndLateBoundProperty2.ts, 0, 40)) diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.types b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.types index 0938c9402a3d6..e43a5e9158425 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.types +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.types @@ -1,9 +1,9 @@ //// [tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts] //// === mappedTypeWithAsClauseAndLateBoundProperty2.ts === -export const thing = (null as any as { [K in keyof number[] as Exclude]: (number[])[K] }); ->thing : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } ->(null as any as { [K in keyof number[] as Exclude]: (number[])[K] }) : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } ->null as any as { [K in keyof number[] as Exclude]: (number[])[K] } : { [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; readonly [Symbol.unscopables]: { [x: number]: boolean; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; sort?: boolean; splice?: boolean; unshift?: boolean; indexOf?: boolean; lastIndexOf?: boolean; every?: boolean; some?: boolean; forEach?: boolean; map?: boolean; filter?: boolean; reduce?: boolean; reduceRight?: boolean; find?: boolean; findIndex?: boolean; fill?: boolean; copyWithin?: boolean; entries?: boolean; keys?: boolean; values?: boolean; includes?: boolean; flatMap?: boolean; flat?: boolean; [Symbol.iterator]?: boolean; readonly [Symbol.unscopables]?: boolean; }; } +export const thing = (null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }); +>thing : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } +>(null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }) : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } +>null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] } : { [x: number]: number; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: { [x: number]: boolean; }; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; flat: (this: A, depth?: D) => FlatArray[]; } >null as any : any diff --git a/tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts b/tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts new file mode 100644 index 0000000000000..e20c9fce401f3 --- /dev/null +++ b/tests/cases/compiler/mappedTypeHomomorphicTupleInstantiationNameTypeKeys.ts @@ -0,0 +1,13 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/pull/55774#issuecomment-1813484949 + +type Mapper = { + [K in keyof T as K]: T[K] extends NonNullable ? T[K] : never; +}; + +type Mapped = Mapper<[1, 2]>; +type Keys = keyof Mapper<[1, 2]>; + +type SomeType = Mapped[Keys]; // ok diff --git a/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts b/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts new file mode 100644 index 0000000000000..bacdd06a46743 --- /dev/null +++ b/tests/cases/compiler/mappedTypeTupleConstraintTypeParameterInNameType.ts @@ -0,0 +1,50 @@ +// @strict: true +// @noEmit: true + +// 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; +const v2_2: string = struct2.b; +const v2_3: bigint = struct2.c; diff --git a/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts b/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts index 5aea06b8b5adf..59e3a3d662842 100644 --- a/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts +++ b/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts @@ -1,4 +1,4 @@ // @target: ES2020 declare let tgt2: number[]; -declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; +declare let src2: { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] }; tgt2 = src2; // Should error diff --git a/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts b/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts index 1cb22a7305783..cd0b1d9cf57a2 100644 --- a/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts +++ b/tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts @@ -1,3 +1,3 @@ // @target: ES2020 // @declaration: true -export const thing = (null as any as { [K in keyof number[] as Exclude]: (number[])[K] }); +export const thing = (null as any as { [K in keyof number[] & PropertyKey as Exclude]: (number[])[K] });