From 2c4cbd98fa87c443bbf98ce3c91c3ea159999d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 30 Nov 2023 17:21:05 +0100 Subject: [PATCH 01/12] Defer index types on remapping mapped types (#55140) Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 25 +- .../reference/mappedTypeAsClauses.errors.txt | 28 +- .../reference/mappedTypeAsClauses.js | 54 +- .../reference/mappedTypeAsClauses.symbols | 587 ++++++++++-------- .../reference/mappedTypeAsClauses.types | 57 +- .../types/mapped/mappedTypeAsClauses.ts | 26 +- 6 files changed, 504 insertions(+), 273 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d21bd56c40c..c6d9f9de3bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1304,6 +1304,12 @@ const enum MappedTypeModifiers { ExcludeOptional = 1 << 3, } +const enum MappedTypeNameTypeKind { + None, + Filtering, + Remapping, +} + const enum ExpandingFlags { None = 0, Source = 1, @@ -13741,7 +13747,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constraintType = getConstraintTypeFromMappedType(type); const mappedType = (type.target as MappedType) || type; const nameType = getNameTypeFromMappedType(mappedType); - const shouldLinkPropDeclarations = !nameType || isFilteringMappedType(mappedType); + const shouldLinkPropDeclarations = getMappedTypeNameTypeKind(mappedType) !== MappedTypeNameTypeKind.Remapping; const templateType = getTemplateTypeFromMappedType(mappedType); const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' const templateModifiers = getMappedTypeModifiers(type); @@ -13923,9 +13929,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function isFilteringMappedType(type: MappedType): boolean { + function getMappedTypeNameTypeKind(type: MappedType): MappedTypeNameTypeKind { const nameType = getNameTypeFromMappedType(type); - return !!nameType && isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type)); + if (!nameType) { + return MappedTypeNameTypeKind.None; + } + return isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type)) ? MappedTypeNameTypeKind.Filtering : MappedTypeNameTypeKind.Remapping; } function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { @@ -17700,7 +17709,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) { return !!(type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || - isGenericMappedType(type) && !hasDistributiveNameType(type) || + isGenericMappedType(type) && (!hasDistributiveNameType(type) || getMappedTypeNameTypeKind(type) === MappedTypeNameTypeKind.Remapping) || type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) || type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType)); } @@ -18282,7 +18291,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P. // For example, for an index access { [P in K]: Box }[X], we construct the type Box. if (isGenericMappedType(objectType)) { - if (!getNameTypeFromMappedType(objectType) || isFilteringMappedType(objectType)) { + if (getMappedTypeNameTypeKind(objectType) !== MappedTypeNameTypeKind.Remapping) { return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing)); } } @@ -40108,7 +40117,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Check if the index type is assignable to 'keyof T' for the object type. const objectType = (type as IndexedAccessType).objectType; const indexType = (type as IndexedAccessType).indexType; - if (isTypeAssignableTo(indexType, getIndexType(objectType, IndexFlags.None))) { + // skip index type deferral on remapping mapped types + const objectIndexType = isGenericMappedType(objectType) && getMappedTypeNameTypeKind(objectType) === MappedTypeNameTypeKind.Remapping + ? getIndexTypeForMappedType(objectType, IndexFlags.None) + : getIndexType(objectType, IndexFlags.None); + if (isTypeAssignableTo(indexType, objectIndexType)) { if ( accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly diff --git a/tests/baselines/reference/mappedTypeAsClauses.errors.txt b/tests/baselines/reference/mappedTypeAsClauses.errors.txt index 5f59683d955..2a8538e6860 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.errors.txt +++ b/tests/baselines/reference/mappedTypeAsClauses.errors.txt @@ -1,4 +1,4 @@ -mappedTypeAsClauses.ts(130,3): error TS2345: Argument of type '"a"' is not assignable to parameter of type '"b"'. +mappedTypeAsClauses.ts(131,3): error TS2345: Argument of type '"a"' is not assignable to parameter of type '"b"'. ==== mappedTypeAsClauses.ts (1 errors) ==== @@ -30,7 +30,8 @@ mappedTypeAsClauses.ts(130,3): error TS2345: Argument of type '"a"' is not assig type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' - type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` + type TD3 = keyof DoubleProp; // keyof DoubleProp + type TD4 = TD3<{ a: string, b: number }>; // 'a1' | 'a2' | 'b1' | 'b2' // Repro from #40619 @@ -155,4 +156,27 @@ mappedTypeAsClauses.ts(130,3): error TS2345: Argument of type '"a"' is not assig type TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; type TN4 = keyof { [K in keyof T as (K extends U ? T[K] : never) extends T[K] ? K : never]: string }; type TN5 = keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K : never]: true }]: string }; + + // repro from https://github.com/microsoft/TypeScript/issues/55129 + type Fruit = + | { + name: "apple"; + color: "red"; + } + | { + name: "banana"; + color: "yellow"; + } + | { + name: "orange"; + color: "orange"; + }; + type Result1 = { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown + }; + type Result2 = keyof { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown + } + type Test1 = keyof Result1 // "apple:red" | "banana:yellow" | "orange:orange" + type Test2 = Result2 // "apple:red" | "banana:yellow" | "orange:orange" \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeAsClauses.js b/tests/baselines/reference/mappedTypeAsClauses.js index be8cfd61431..9f401c2f1ce 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.js +++ b/tests/baselines/reference/mappedTypeAsClauses.js @@ -29,7 +29,8 @@ type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | numbe type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' -type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` +type TD3 = keyof DoubleProp; // keyof DoubleProp +type TD4 = TD3<{ a: string, b: number }>; // 'a1' | 'a2' | 'b1' | 'b2' // Repro from #40619 @@ -152,6 +153,29 @@ type TN2 = keyof { [P in keyof T as 'a' extends P ? 'x' : 'y']: string }; type TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; type TN4 = keyof { [K in keyof T as (K extends U ? T[K] : never) extends T[K] ? K : never]: string }; type TN5 = keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K : never]: true }]: string }; + +// repro from https://github.com/microsoft/TypeScript/issues/55129 +type Fruit = + | { + name: "apple"; + color: "red"; + } + | { + name: "banana"; + color: "yellow"; + } + | { + name: "orange"; + color: "orange"; + }; +type Result1 = { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +}; +type Result2 = keyof { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +} +type Test1 = keyof Result1 // "apple:red" | "banana:yellow" | "orange:orange" +type Test2 = Result2 // "apple:red" | "banana:yellow" | "orange:orange" //// [mappedTypeAsClauses.js] @@ -217,6 +241,10 @@ type TD1 = DoubleProp<{ }>; type TD2 = keyof TD1; type TD3 = keyof DoubleProp; +type TD4 = TD3<{ + a: string; + b: number; +}>; type Lazyify = { [K in keyof T as `get${Capitalize}`]: () => T[K]; }; @@ -337,3 +365,27 @@ type TN5 = keyof { [P in K as T[P] extends U ? K : never]: true; }]: string; }; +type Fruit = { + name: "apple"; + color: "red"; +} | { + name: "banana"; + color: "yellow"; +} | { + name: "orange"; + color: "orange"; +}; +type Result1 = { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown; +}; +type Result2 = keyof { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown; +}; +type Test1 = keyof Result1; +type Test2 = Result2; diff --git a/tests/baselines/reference/mappedTypeAsClauses.symbols b/tests/baselines/reference/mappedTypeAsClauses.symbols index 6028775c7b3..ebb570f319e 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.symbols +++ b/tests/baselines/reference/mappedTypeAsClauses.symbols @@ -105,440 +105,507 @@ type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' >TD2 : Symbol(TD2, Decl(mappedTypeAsClauses.ts, 26, 48)) >TD1 : Symbol(TD1, Decl(mappedTypeAsClauses.ts, 25, 75)) -type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` +type TD3 = keyof DoubleProp; // keyof DoubleProp >TD3 : Symbol(TD3, Decl(mappedTypeAsClauses.ts, 27, 21)) >U : Symbol(U, Decl(mappedTypeAsClauses.ts, 28, 9)) >DoubleProp : Symbol(DoubleProp, Decl(mappedTypeAsClauses.ts, 21, 85)) >U : Symbol(U, Decl(mappedTypeAsClauses.ts, 28, 9)) +type TD4 = TD3<{ a: string, b: number }>; // 'a1' | 'a2' | 'b1' | 'b2' +>TD4 : Symbol(TD4, Decl(mappedTypeAsClauses.ts, 28, 34)) +>TD3 : Symbol(TD3, Decl(mappedTypeAsClauses.ts, 27, 21)) +>a : Symbol(a, Decl(mappedTypeAsClauses.ts, 29, 16)) +>b : Symbol(b, Decl(mappedTypeAsClauses.ts, 29, 27)) + // Repro from #40619 type Lazyify = { ->Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 28, 34)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) +>Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 29, 41)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 33, 13)) [K in keyof T as `get${Capitalize}`]: () => T[K] ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 34, 5)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 33, 13)) >Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 34, 5)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 33, 13)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 34, 5)) }; interface Person { ->Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 34, 2)) +>Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 35, 2)) readonly name: string; ->name : Symbol(Person.name, Decl(mappedTypeAsClauses.ts, 36, 18)) +>name : Symbol(Person.name, Decl(mappedTypeAsClauses.ts, 37, 18)) age: number; ->age : Symbol(Person.age, Decl(mappedTypeAsClauses.ts, 37, 26)) +>age : Symbol(Person.age, Decl(mappedTypeAsClauses.ts, 38, 26)) location?: string; ->location : Symbol(Person.location, Decl(mappedTypeAsClauses.ts, 38, 16)) +>location : Symbol(Person.location, Decl(mappedTypeAsClauses.ts, 39, 16)) } type LazyPerson = Lazyify; ->LazyPerson : Symbol(LazyPerson, Decl(mappedTypeAsClauses.ts, 40, 1)) ->Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 28, 34)) ->Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 34, 2)) +>LazyPerson : Symbol(LazyPerson, Decl(mappedTypeAsClauses.ts, 41, 1)) +>Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 29, 41)) +>Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 35, 2)) // Repro from #40833 type Example = {foo: string, bar: number}; ->Example : Symbol(Example, Decl(mappedTypeAsClauses.ts, 42, 34)) ->foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 46, 16)) ->bar : Symbol(bar, Decl(mappedTypeAsClauses.ts, 46, 28)) +>Example : Symbol(Example, Decl(mappedTypeAsClauses.ts, 43, 34)) +>foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 47, 16)) +>bar : Symbol(bar, Decl(mappedTypeAsClauses.ts, 47, 28)) type PickByValueType = { ->PickByValueType : Symbol(PickByValueType, Decl(mappedTypeAsClauses.ts, 46, 42)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 48, 21)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 48, 23)) +>PickByValueType : Symbol(PickByValueType, Decl(mappedTypeAsClauses.ts, 47, 42)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 49, 21)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 49, 23)) [K in keyof T as T[K] extends U ? K : never]: T[K] ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 49, 3)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 48, 21)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 48, 21)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 49, 3)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 48, 23)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 49, 3)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 48, 21)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 49, 3)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 50, 3)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 49, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 49, 21)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 50, 3)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 49, 23)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 50, 3)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 49, 21)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 50, 3)) }; type T1 = PickByValueType; ->T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 50, 2)) ->PickByValueType : Symbol(PickByValueType, Decl(mappedTypeAsClauses.ts, 46, 42)) ->Example : Symbol(Example, Decl(mappedTypeAsClauses.ts, 42, 34)) +>T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 51, 2)) +>PickByValueType : Symbol(PickByValueType, Decl(mappedTypeAsClauses.ts, 47, 42)) +>Example : Symbol(Example, Decl(mappedTypeAsClauses.ts, 43, 34)) const e1: T1 = { ->e1 : Symbol(e1, Decl(mappedTypeAsClauses.ts, 53, 5)) ->T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 50, 2)) +>e1 : Symbol(e1, Decl(mappedTypeAsClauses.ts, 54, 5)) +>T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 51, 2)) foo: "hello" ->foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 53, 16)) +>foo : Symbol(foo, Decl(mappedTypeAsClauses.ts, 54, 16)) }; type T2 = keyof T1; ->T2 : Symbol(T2, Decl(mappedTypeAsClauses.ts, 55, 2)) ->T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 50, 2)) +>T2 : Symbol(T2, Decl(mappedTypeAsClauses.ts, 56, 2)) +>T1 : Symbol(T1, Decl(mappedTypeAsClauses.ts, 51, 2)) const e2: T2 = "foo"; ->e2 : Symbol(e2, Decl(mappedTypeAsClauses.ts, 57, 5)) ->T2 : Symbol(T2, Decl(mappedTypeAsClauses.ts, 55, 2)) +>e2 : Symbol(e2, Decl(mappedTypeAsClauses.ts, 58, 5)) +>T2 : Symbol(T2, Decl(mappedTypeAsClauses.ts, 56, 2)) // Repro from #41133 interface Car { ->Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 57, 21)) +>Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 58, 21)) name: string; ->name : Symbol(Car.name, Decl(mappedTypeAsClauses.ts, 61, 15)) +>name : Symbol(Car.name, Decl(mappedTypeAsClauses.ts, 62, 15)) seats: number; ->seats : Symbol(Car.seats, Decl(mappedTypeAsClauses.ts, 62, 17)) +>seats : Symbol(Car.seats, Decl(mappedTypeAsClauses.ts, 63, 17)) engine: Engine; ->engine : Symbol(Car.engine, Decl(mappedTypeAsClauses.ts, 63, 18)) ->Engine : Symbol(Engine, Decl(mappedTypeAsClauses.ts, 66, 1)) +>engine : Symbol(Car.engine, Decl(mappedTypeAsClauses.ts, 64, 18)) +>Engine : Symbol(Engine, Decl(mappedTypeAsClauses.ts, 67, 1)) wheels: Wheel[]; ->wheels : Symbol(Car.wheels, Decl(mappedTypeAsClauses.ts, 64, 19)) ->Wheel : Symbol(Wheel, Decl(mappedTypeAsClauses.ts, 71, 1)) +>wheels : Symbol(Car.wheels, Decl(mappedTypeAsClauses.ts, 65, 19)) +>Wheel : Symbol(Wheel, Decl(mappedTypeAsClauses.ts, 72, 1)) } interface Engine { ->Engine : Symbol(Engine, Decl(mappedTypeAsClauses.ts, 66, 1)) +>Engine : Symbol(Engine, Decl(mappedTypeAsClauses.ts, 67, 1)) manufacturer: string; ->manufacturer : Symbol(Engine.manufacturer, Decl(mappedTypeAsClauses.ts, 68, 18)) +>manufacturer : Symbol(Engine.manufacturer, Decl(mappedTypeAsClauses.ts, 69, 18)) horsepower: number; ->horsepower : Symbol(Engine.horsepower, Decl(mappedTypeAsClauses.ts, 69, 25)) +>horsepower : Symbol(Engine.horsepower, Decl(mappedTypeAsClauses.ts, 70, 25)) } interface Wheel { ->Wheel : Symbol(Wheel, Decl(mappedTypeAsClauses.ts, 71, 1)) +>Wheel : Symbol(Wheel, Decl(mappedTypeAsClauses.ts, 72, 1)) type: "summer" | "winter"; ->type : Symbol(Wheel.type, Decl(mappedTypeAsClauses.ts, 73, 17)) +>type : Symbol(Wheel.type, Decl(mappedTypeAsClauses.ts, 74, 17)) radius: number; ->radius : Symbol(Wheel.radius, Decl(mappedTypeAsClauses.ts, 74, 30)) +>radius : Symbol(Wheel.radius, Decl(mappedTypeAsClauses.ts, 75, 30)) } type Primitive = string | number | boolean; ->Primitive : Symbol(Primitive, Decl(mappedTypeAsClauses.ts, 76, 1)) +>Primitive : Symbol(Primitive, Decl(mappedTypeAsClauses.ts, 77, 1)) type OnlyPrimitives = { [K in keyof T as T[K] extends Primitive ? K : never]: T[K] }; ->OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 78, 43)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 79, 20)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 79, 28)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 79, 20)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 79, 20)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 79, 28)) ->Primitive : Symbol(Primitive, Decl(mappedTypeAsClauses.ts, 76, 1)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 79, 28)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 79, 20)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 79, 28)) +>OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 79, 43)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 80, 20)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 80, 28)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 80, 20)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 80, 20)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 80, 28)) +>Primitive : Symbol(Primitive, Decl(mappedTypeAsClauses.ts, 77, 1)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 80, 28)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 80, 20)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 80, 28)) let primitiveCar: OnlyPrimitives; // { name: string; seats: number; } ->primitiveCar : Symbol(primitiveCar, Decl(mappedTypeAsClauses.ts, 81, 3)) ->OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 78, 43)) ->Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 57, 21)) +>primitiveCar : Symbol(primitiveCar, Decl(mappedTypeAsClauses.ts, 82, 3)) +>OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 79, 43)) +>Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 58, 21)) let keys: keyof OnlyPrimitives; // "name" | "seats" ->keys : Symbol(keys, Decl(mappedTypeAsClauses.ts, 82, 3)) ->OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 78, 43)) ->Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 57, 21)) +>keys : Symbol(keys, Decl(mappedTypeAsClauses.ts, 83, 3)) +>OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 79, 43)) +>Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 58, 21)) type KeysOfPrimitives = keyof OnlyPrimitives; ->KeysOfPrimitives : Symbol(KeysOfPrimitives, Decl(mappedTypeAsClauses.ts, 82, 36)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 84, 22)) ->OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 78, 43)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 84, 22)) +>KeysOfPrimitives : Symbol(KeysOfPrimitives, Decl(mappedTypeAsClauses.ts, 83, 36)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 85, 22)) +>OnlyPrimitives : Symbol(OnlyPrimitives, Decl(mappedTypeAsClauses.ts, 79, 43)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 85, 22)) let carKeys: KeysOfPrimitives; // "name" | "seats" ->carKeys : Symbol(carKeys, Decl(mappedTypeAsClauses.ts, 86, 3)) ->KeysOfPrimitives : Symbol(KeysOfPrimitives, Decl(mappedTypeAsClauses.ts, 82, 36)) ->Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 57, 21)) +>carKeys : Symbol(carKeys, Decl(mappedTypeAsClauses.ts, 87, 3)) +>KeysOfPrimitives : Symbol(KeysOfPrimitives, Decl(mappedTypeAsClauses.ts, 83, 36)) +>Car : Symbol(Car, Decl(mappedTypeAsClauses.ts, 58, 21)) // Repro from #41453 type Equal = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false; ->Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 86, 35)) ->A : Symbol(A, Decl(mappedTypeAsClauses.ts, 90, 11)) ->B : Symbol(B, Decl(mappedTypeAsClauses.ts, 90, 13)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 90, 21)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 90, 21)) ->A : Symbol(A, Decl(mappedTypeAsClauses.ts, 90, 11)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 90, 60)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 90, 60)) ->B : Symbol(B, Decl(mappedTypeAsClauses.ts, 90, 13)) +>Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 87, 35)) +>A : Symbol(A, Decl(mappedTypeAsClauses.ts, 91, 11)) +>B : Symbol(B, Decl(mappedTypeAsClauses.ts, 91, 13)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 91, 21)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 91, 21)) +>A : Symbol(A, Decl(mappedTypeAsClauses.ts, 91, 11)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 91, 60)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 91, 60)) +>B : Symbol(B, Decl(mappedTypeAsClauses.ts, 91, 13)) type If = Cond extends true ? Then : Else; ->If : Symbol(If, Decl(mappedTypeAsClauses.ts, 90, 104)) ->Cond : Symbol(Cond, Decl(mappedTypeAsClauses.ts, 92, 8)) ->Then : Symbol(Then, Decl(mappedTypeAsClauses.ts, 92, 29)) ->Else : Symbol(Else, Decl(mappedTypeAsClauses.ts, 92, 35)) ->Cond : Symbol(Cond, Decl(mappedTypeAsClauses.ts, 92, 8)) ->Then : Symbol(Then, Decl(mappedTypeAsClauses.ts, 92, 29)) ->Else : Symbol(Else, Decl(mappedTypeAsClauses.ts, 92, 35)) +>If : Symbol(If, Decl(mappedTypeAsClauses.ts, 91, 104)) +>Cond : Symbol(Cond, Decl(mappedTypeAsClauses.ts, 93, 8)) +>Then : Symbol(Then, Decl(mappedTypeAsClauses.ts, 93, 29)) +>Else : Symbol(Else, Decl(mappedTypeAsClauses.ts, 93, 35)) +>Cond : Symbol(Cond, Decl(mappedTypeAsClauses.ts, 93, 8)) +>Then : Symbol(Then, Decl(mappedTypeAsClauses.ts, 93, 29)) +>Else : Symbol(Else, Decl(mappedTypeAsClauses.ts, 93, 35)) type GetKey = keyof { [TP in keyof S as Equal extends true ? TP : never]: any }; ->GetKey : Symbol(GetKey, Decl(mappedTypeAsClauses.ts, 92, 76)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 94, 12)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 94, 14)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 94, 29)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 94, 12)) ->Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 86, 35)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 94, 12)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 94, 29)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 94, 14)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 94, 29)) +>GetKey : Symbol(GetKey, Decl(mappedTypeAsClauses.ts, 93, 76)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 95, 12)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 95, 14)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 95, 29)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 95, 12)) +>Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 87, 35)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 95, 12)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 95, 29)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 95, 14)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 95, 29)) type GetKeyWithIf = keyof { [TP in keyof S as If, TP, never>]: any }; ->GetKeyWithIf : Symbol(GetKeyWithIf, Decl(mappedTypeAsClauses.ts, 94, 96)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 96, 18)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 96, 20)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 96, 35)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 96, 18)) ->If : Symbol(If, Decl(mappedTypeAsClauses.ts, 90, 104)) ->Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 86, 35)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 96, 18)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 96, 35)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 96, 20)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 96, 35)) +>GetKeyWithIf : Symbol(GetKeyWithIf, Decl(mappedTypeAsClauses.ts, 95, 96)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 97, 18)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 97, 20)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 97, 35)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 97, 18)) +>If : Symbol(If, Decl(mappedTypeAsClauses.ts, 91, 104)) +>Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 87, 35)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 97, 18)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 97, 35)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 97, 20)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 97, 35)) type GetObjWithIf = { [TP in keyof S as If, TP, never>]: any }; ->GetObjWithIf : Symbol(GetObjWithIf, Decl(mappedTypeAsClauses.ts, 96, 91)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 98, 18)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 98, 20)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 98, 29)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 98, 18)) ->If : Symbol(If, Decl(mappedTypeAsClauses.ts, 90, 104)) ->Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 86, 35)) ->S : Symbol(S, Decl(mappedTypeAsClauses.ts, 98, 18)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 98, 29)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 98, 20)) ->TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 98, 29)) +>GetObjWithIf : Symbol(GetObjWithIf, Decl(mappedTypeAsClauses.ts, 97, 91)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 99, 18)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 99, 20)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 99, 29)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 99, 18)) +>If : Symbol(If, Decl(mappedTypeAsClauses.ts, 91, 104)) +>Equal : Symbol(Equal, Decl(mappedTypeAsClauses.ts, 87, 35)) +>S : Symbol(S, Decl(mappedTypeAsClauses.ts, 99, 18)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 99, 29)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 99, 20)) +>TP : Symbol(TP, Decl(mappedTypeAsClauses.ts, 99, 29)) type Task = { ->Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 98, 85)) +>Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 99, 85)) isDone: boolean; ->isDone : Symbol(isDone, Decl(mappedTypeAsClauses.ts, 100, 13)) +>isDone : Symbol(isDone, Decl(mappedTypeAsClauses.ts, 101, 13)) }; type Schema = { ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) root: { ->root : Symbol(root, Decl(mappedTypeAsClauses.ts, 104, 15)) +>root : Symbol(root, Decl(mappedTypeAsClauses.ts, 105, 15)) title: string; ->title : Symbol(title, Decl(mappedTypeAsClauses.ts, 105, 9)) +>title : Symbol(title, Decl(mappedTypeAsClauses.ts, 106, 9)) task: Task; ->task : Symbol(task, Decl(mappedTypeAsClauses.ts, 106, 18)) ->Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 98, 85)) +>task : Symbol(task, Decl(mappedTypeAsClauses.ts, 107, 18)) +>Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 99, 85)) } Task: Task; ->Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 108, 3)) ->Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 98, 85)) +>Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 109, 3)) +>Task : Symbol(Task, Decl(mappedTypeAsClauses.ts, 99, 85)) }; type Res1 = GetKey; // "Task" ->Res1 : Symbol(Res1, Decl(mappedTypeAsClauses.ts, 110, 2)) ->GetKey : Symbol(GetKey, Decl(mappedTypeAsClauses.ts, 92, 76)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) +>Res1 : Symbol(Res1, Decl(mappedTypeAsClauses.ts, 111, 2)) +>GetKey : Symbol(GetKey, Decl(mappedTypeAsClauses.ts, 93, 76)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) type Res2 = GetKeyWithIf; // "Task" ->Res2 : Symbol(Res2, Decl(mappedTypeAsClauses.ts, 112, 51)) ->GetKeyWithIf : Symbol(GetKeyWithIf, Decl(mappedTypeAsClauses.ts, 94, 96)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) +>Res2 : Symbol(Res2, Decl(mappedTypeAsClauses.ts, 113, 51)) +>GetKeyWithIf : Symbol(GetKeyWithIf, Decl(mappedTypeAsClauses.ts, 95, 96)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) type Res3 = keyof GetObjWithIf; // "Task" ->Res3 : Symbol(Res3, Decl(mappedTypeAsClauses.ts, 113, 57)) ->GetObjWithIf : Symbol(GetObjWithIf, Decl(mappedTypeAsClauses.ts, 96, 91)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) ->Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 102, 2)) +>Res3 : Symbol(Res3, Decl(mappedTypeAsClauses.ts, 114, 57)) +>GetObjWithIf : Symbol(GetObjWithIf, Decl(mappedTypeAsClauses.ts, 97, 91)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) +>Schema : Symbol(Schema, Decl(mappedTypeAsClauses.ts, 103, 2)) // Repro from #44019 type KeysExtendedBy = keyof { [K in keyof T as U extends T[K] ? K : never] : T[K] }; ->KeysExtendedBy : Symbol(KeysExtendedBy, Decl(mappedTypeAsClauses.ts, 114, 63)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 118, 20)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 118, 22)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 118, 37)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 118, 20)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 118, 22)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 118, 20)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 118, 37)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 118, 37)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 118, 20)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 118, 37)) +>KeysExtendedBy : Symbol(KeysExtendedBy, Decl(mappedTypeAsClauses.ts, 115, 63)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 119, 20)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 119, 22)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 119, 37)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 119, 20)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 119, 22)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 119, 20)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 119, 37)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 119, 37)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 119, 20)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 119, 37)) interface M { ->M : Symbol(M, Decl(mappedTypeAsClauses.ts, 118, 90)) +>M : Symbol(M, Decl(mappedTypeAsClauses.ts, 119, 90)) a: boolean; ->a : Symbol(M.a, Decl(mappedTypeAsClauses.ts, 120, 13)) +>a : Symbol(M.a, Decl(mappedTypeAsClauses.ts, 121, 13)) b: number; ->b : Symbol(M.b, Decl(mappedTypeAsClauses.ts, 121, 15)) +>b : Symbol(M.b, Decl(mappedTypeAsClauses.ts, 122, 15)) } function f(x: KeysExtendedBy) { ->f : Symbol(f, Decl(mappedTypeAsClauses.ts, 123, 1)) ->x : Symbol(x, Decl(mappedTypeAsClauses.ts, 125, 11)) ->KeysExtendedBy : Symbol(KeysExtendedBy, Decl(mappedTypeAsClauses.ts, 114, 63)) ->M : Symbol(M, Decl(mappedTypeAsClauses.ts, 118, 90)) +>f : Symbol(f, Decl(mappedTypeAsClauses.ts, 124, 1)) +>x : Symbol(x, Decl(mappedTypeAsClauses.ts, 126, 11)) +>KeysExtendedBy : Symbol(KeysExtendedBy, Decl(mappedTypeAsClauses.ts, 115, 63)) +>M : Symbol(M, Decl(mappedTypeAsClauses.ts, 119, 90)) return x; ->x : Symbol(x, Decl(mappedTypeAsClauses.ts, 125, 11)) +>x : Symbol(x, Decl(mappedTypeAsClauses.ts, 126, 11)) } f("a"); // Error, should allow only "b" ->f : Symbol(f, Decl(mappedTypeAsClauses.ts, 123, 1)) +>f : Symbol(f, Decl(mappedTypeAsClauses.ts, 124, 1)) type NameMap = { 'a': 'x', 'b': 'y', 'c': 'z' }; ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) ->'a' : Symbol('a', Decl(mappedTypeAsClauses.ts, 131, 16)) ->'b' : Symbol('b', Decl(mappedTypeAsClauses.ts, 131, 26)) ->'c' : Symbol('c', Decl(mappedTypeAsClauses.ts, 131, 36)) +>NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 130, 7)) +>'a' : Symbol('a', Decl(mappedTypeAsClauses.ts, 132, 16)) +>'b' : Symbol('b', Decl(mappedTypeAsClauses.ts, 132, 26)) +>'c' : Symbol('c', Decl(mappedTypeAsClauses.ts, 132, 36)) // Distributive, will be simplified type TS0 = keyof { [P in keyof T as keyof Record]: string }; ->TS0 : Symbol(TS0, Decl(mappedTypeAsClauses.ts, 131, 48)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 135, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 135, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 135, 9)) +>TS0 : Symbol(TS0, Decl(mappedTypeAsClauses.ts, 132, 48)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 136, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 136, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 136, 9)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 135, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 136, 23)) type TS1 = keyof { [P in keyof T as Extract]: string }; ->TS1 : Symbol(TS1, Decl(mappedTypeAsClauses.ts, 135, 74)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 136, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 136, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 136, 9)) +>TS1 : Symbol(TS1, Decl(mappedTypeAsClauses.ts, 136, 74)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 137, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 137, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 137, 9)) >Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 136, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 137, 23)) type TS2 = keyof { [P in keyof T as P & ('a' | 'b' | 'c')]: string }; ->TS2 : Symbol(TS2, Decl(mappedTypeAsClauses.ts, 136, 78)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 137, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 137, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 137, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 137, 23)) +>TS2 : Symbol(TS2, Decl(mappedTypeAsClauses.ts, 137, 78)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 138, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 138, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 138, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 138, 23)) type TS3 = keyof { [P in keyof T as Exclude]: string }; ->TS3 : Symbol(TS3, Decl(mappedTypeAsClauses.ts, 137, 72)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 138, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 138, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 138, 9)) +>TS3 : Symbol(TS3, Decl(mappedTypeAsClauses.ts, 138, 72)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 139, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 139, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 139, 9)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 138, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 139, 23)) type TS4 = keyof { [P in keyof T as NameMap[P & keyof NameMap]]: string }; ->TS4 : Symbol(TS4, Decl(mappedTypeAsClauses.ts, 138, 78)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 139, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 139, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 139, 9)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 139, 23)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) +>TS4 : Symbol(TS4, Decl(mappedTypeAsClauses.ts, 139, 78)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 140, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 140, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 140, 9)) +>NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 130, 7)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 140, 23)) +>NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 130, 7)) type TS5 = keyof { [P in keyof T & keyof NameMap as NameMap[P]]: string }; ->TS5 : Symbol(TS5, Decl(mappedTypeAsClauses.ts, 139, 77)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 140, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 140, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 140, 9)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 140, 23)) +>TS5 : Symbol(TS5, Decl(mappedTypeAsClauses.ts, 140, 77)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 141, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 141, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 141, 9)) +>NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 130, 7)) +>NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 130, 7)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 141, 23)) type TS6 = keyof { [ K in keyof T as V & (K extends U ? K : never)]: string }; ->TS6 : Symbol(TS6, Decl(mappedTypeAsClauses.ts, 140, 77)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 141, 9)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 141, 11)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 141, 14)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 141, 29)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 141, 9)) ->V : Symbol(V, Decl(mappedTypeAsClauses.ts, 141, 14)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 141, 29)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 141, 11)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 141, 29)) +>TS6 : Symbol(TS6, Decl(mappedTypeAsClauses.ts, 141, 77)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 142, 9)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 142, 11)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 142, 14)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 142, 29)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 142, 9)) +>V : Symbol(V, Decl(mappedTypeAsClauses.ts, 142, 14)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 142, 29)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 142, 11)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 142, 29)) // Non-distributive, won't be simplified type TN0 = keyof { [P in keyof T as T[P] extends number ? P : never]: string }; ->TN0 : Symbol(TN0, Decl(mappedTypeAsClauses.ts, 141, 87)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 145, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 145, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 145, 9)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 145, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 145, 23)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 145, 23)) +>TN0 : Symbol(TN0, Decl(mappedTypeAsClauses.ts, 142, 87)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) type TN1 = keyof { [P in keyof T as number extends T[P] ? P : never]: string }; ->TN1 : Symbol(TN1, Decl(mappedTypeAsClauses.ts, 145, 82)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 146, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) +>TN1 : Symbol(TN1, Decl(mappedTypeAsClauses.ts, 146, 82)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 147, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 147, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 147, 9)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 147, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 147, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 147, 23)) type TN2 = keyof { [P in keyof T as 'a' extends P ? 'x' : 'y']: string }; ->TN2 : Symbol(TN2, Decl(mappedTypeAsClauses.ts, 146, 82)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 147, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 147, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 147, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 147, 23)) +>TN2 : Symbol(TN2, Decl(mappedTypeAsClauses.ts, 147, 82)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 148, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 148, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 148, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 148, 23)) type TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; ->TN3 : Symbol(TN3, Decl(mappedTypeAsClauses.ts, 147, 76)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 148, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 148, 23)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 148, 9)) +>TN3 : Symbol(TN3, Decl(mappedTypeAsClauses.ts, 148, 76)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 149, 23)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 148, 23)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 149, 23)) type TN4 = keyof { [K in keyof T as (K extends U ? T[K] : never) extends T[K] ? K : never]: string }; ->TN4 : Symbol(TN4, Decl(mappedTypeAsClauses.ts, 148, 94)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 149, 11)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 149, 11)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) +>TN4 : Symbol(TN4, Decl(mappedTypeAsClauses.ts, 149, 94)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 150, 11)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 150, 11)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) type TN5 = keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K : never]: true }]: string }; ->TN5 : Symbol(TN5, Decl(mappedTypeAsClauses.ts, 149, 107)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 150, 11)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 150, 51)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) ->T : Symbol(T, Decl(mappedTypeAsClauses.ts, 150, 9)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 150, 51)) ->U : Symbol(U, Decl(mappedTypeAsClauses.ts, 150, 11)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 150, 26)) +>TN5 : Symbol(TN5, Decl(mappedTypeAsClauses.ts, 150, 107)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 151, 9)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 151, 11)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 151, 26)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 151, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 151, 51)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 151, 26)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 151, 9)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 151, 51)) +>U : Symbol(U, Decl(mappedTypeAsClauses.ts, 151, 11)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 151, 26)) + +// repro from https://github.com/microsoft/TypeScript/issues/55129 +type Fruit = +>Fruit : Symbol(Fruit, Decl(mappedTypeAsClauses.ts, 151, 108)) + + | { + name: "apple"; +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 155, 5)) + + color: "red"; +>color : Symbol(color, Decl(mappedTypeAsClauses.ts, 156, 20)) + } + | { + name: "banana"; +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 159, 5)) + + color: "yellow"; +>color : Symbol(color, Decl(mappedTypeAsClauses.ts, 160, 21)) + } + | { + name: "orange"; +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 163, 5)) + + color: "orange"; +>color : Symbol(color, Decl(mappedTypeAsClauses.ts, 164, 21)) + + }; +type Result1 = { +>Result1 : Symbol(Result1, Decl(mappedTypeAsClauses.ts, 166, 6)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 167, 13)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 167, 24)) +>color : Symbol(color, Decl(mappedTypeAsClauses.ts, 167, 46)) + + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 168, 3)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 167, 13)) +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 168, 3)) +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 168, 3)) + +}; +type Result2 = keyof { +>Result2 : Symbol(Result2, Decl(mappedTypeAsClauses.ts, 169, 2)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 170, 13)) +>name : Symbol(name, Decl(mappedTypeAsClauses.ts, 170, 24)) +>color : Symbol(color, Decl(mappedTypeAsClauses.ts, 170, 46)) + + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 171, 3)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 170, 13)) +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 171, 3)) +>Key : Symbol(Key, Decl(mappedTypeAsClauses.ts, 171, 3)) +} +type Test1 = keyof Result1 // "apple:red" | "banana:yellow" | "orange:orange" +>Test1 : Symbol(Test1, Decl(mappedTypeAsClauses.ts, 172, 1)) +>Result1 : Symbol(Result1, Decl(mappedTypeAsClauses.ts, 166, 6)) +>Fruit : Symbol(Fruit, Decl(mappedTypeAsClauses.ts, 151, 108)) + +type Test2 = Result2 // "apple:red" | "banana:yellow" | "orange:orange" +>Test2 : Symbol(Test2, Decl(mappedTypeAsClauses.ts, 173, 33)) +>Result2 : Symbol(Result2, Decl(mappedTypeAsClauses.ts, 169, 2)) +>Fruit : Symbol(Fruit, Decl(mappedTypeAsClauses.ts, 151, 108)) diff --git a/tests/baselines/reference/mappedTypeAsClauses.types b/tests/baselines/reference/mappedTypeAsClauses.types index f9d426c0e8f..168e8bd6eaf 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.types +++ b/tests/baselines/reference/mappedTypeAsClauses.types @@ -65,8 +65,13 @@ type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' >TD2 : "a1" | "b1" | "a2" | "b2" -type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` ->TD3 : `${keyof U & string}1` | `${keyof U & string}2` +type TD3 = keyof DoubleProp; // keyof DoubleProp +>TD3 : keyof DoubleProp + +type TD4 = TD3<{ a: string, b: number }>; // 'a1' | 'a2' | 'b1' | 'b2' +>TD4 : "a1" | "b1" | "a2" | "b2" +>a : string +>b : number // Repro from #40619 @@ -277,7 +282,7 @@ type TS4 = keyof { [P in keyof T as NameMap[P & keyof NameMap]]: string }; >TS4 : keyof { [P in keyof T as NameMap[P & keyof NameMap]]: string; } type TS5 = keyof { [P in keyof T & keyof NameMap as NameMap[P]]: string }; ->TS5 : NameMap[keyof T & "a"] | NameMap[keyof T & "b"] | NameMap[keyof T & "c"] +>TS5 : keyof { [P in keyof T & keyof NameMap as NameMap[P]]: string; } type TS6 = keyof { [ K in keyof T as V & (K extends U ? K : never)]: string }; >TS6 : keyof { [K in keyof T as V & (K extends U ? K : never)]: string; } @@ -303,3 +308,49 @@ type TN5 = keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K >TN5 : keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K : never]: true; }]: string; } >true : true +// repro from https://github.com/microsoft/TypeScript/issues/55129 +type Fruit = +>Fruit : { name: "apple"; color: "red"; } | { name: "banana"; color: "yellow"; } | { name: "orange"; color: "orange"; } + + | { + name: "apple"; +>name : "apple" + + color: "red"; +>color : "red" + } + | { + name: "banana"; +>name : "banana" + + color: "yellow"; +>color : "yellow" + } + | { + name: "orange"; +>name : "orange" + + color: "orange"; +>color : "orange" + + }; +type Result1 = { +>Result1 : Result1 +>name : string | number +>color : string | number + + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +}; +type Result2 = keyof { +>Result2 : keyof { [Key in T as `${Key["name"]}:${Key["color"]}`]: unknown; } +>name : string | number +>color : string | number + + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +} +type Test1 = keyof Result1 // "apple:red" | "banana:yellow" | "orange:orange" +>Test1 : "apple:red" | "banana:yellow" | "orange:orange" + +type Test2 = Result2 // "apple:red" | "banana:yellow" | "orange:orange" +>Test2 : "apple:red" | "banana:yellow" | "orange:orange" + diff --git a/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts index ba0222660b8..9256a4541fe 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts @@ -29,7 +29,8 @@ type TM1 = Methods<{ foo(): number, bar(x: string): boolean, baz: string | numbe type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' -type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` +type TD3 = keyof DoubleProp; // keyof DoubleProp +type TD4 = TD3<{ a: string, b: number }>; // 'a1' | 'a2' | 'b1' | 'b2' // Repro from #40619 @@ -152,3 +153,26 @@ type TN2 = keyof { [P in keyof T as 'a' extends P ? 'x' : 'y']: string }; type TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; type TN4 = keyof { [K in keyof T as (K extends U ? T[K] : never) extends T[K] ? K : never]: string }; type TN5 = keyof { [K in keyof T as keyof { [P in K as T[P] extends U ? K : never]: true }]: string }; + +// repro from https://github.com/microsoft/TypeScript/issues/55129 +type Fruit = + | { + name: "apple"; + color: "red"; + } + | { + name: "banana"; + color: "yellow"; + } + | { + name: "orange"; + color: "orange"; + }; +type Result1 = { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +}; +type Result2 = keyof { + [Key in T as `${Key['name']}:${Key['color']}`]: unknown +} +type Test1 = keyof Result1 // "apple:red" | "banana:yellow" | "orange:orange" +type Test2 = Result2 // "apple:red" | "banana:yellow" | "orange:orange" From eb2046d04634da6087964a959fd2e08514f3a8c2 Mon Sep 17 00:00:00 2001 From: Andrea Simone Costa Date: Thu, 30 Nov 2023 20:21:28 +0100 Subject: [PATCH 02/12] Reverse mapped types with intersection constraint (#55811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mateusz BurzyƄski Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 31 +- ...appedTypeIntersectionConstraint.errors.txt | 225 ++++++++ ...reverseMappedTypeIntersectionConstraint.js | 260 ++++++++++ ...seMappedTypeIntersectionConstraint.symbols | 491 ++++++++++++++++++ ...erseMappedTypeIntersectionConstraint.types | 461 ++++++++++++++++ ...erseMappedTypeLimitedConstraint.errors.txt | 24 + .../reverseMappedTypeLimitedConstraint.js | 28 + ...reverseMappedTypeLimitedConstraint.symbols | 55 ++ .../reverseMappedTypeLimitedConstraint.types | 52 ++ ...reverseMappedTypeIntersectionConstraint.ts | 174 +++++++ .../reverseMappedTypeLimitedConstraint.ts | 15 + 11 files changed, 1814 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt create mode 100644 tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js create mode 100644 tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols create mode 100644 tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types create mode 100644 tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt create mode 100644 tests/baselines/reference/reverseMappedTypeLimitedConstraint.js create mode 100644 tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols create mode 100644 tests/baselines/reference/reverseMappedTypeLimitedConstraint.types create mode 100644 tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts create mode 100644 tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6d9f9de3bd..ea86fc74de3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13647,6 +13647,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])])); } + // If the original mapped type had an intersection constraint we extract its components, + // and we make an attempt to do so even if the intersection has been reduced to a union. + // This entire process allows us to possibly retrieve the filtering type literals. + // e.g. { [K in keyof U & ("a" | "b") ] } -> "a" | "b" + function getLimitedConstraint(type: ReverseMappedType) { + const constraint = getConstraintTypeFromMappedType(type.mappedType); + if (!(constraint.flags & TypeFlags.Union || constraint.flags & TypeFlags.Intersection)) { + return; + } + const origin = (constraint.flags & TypeFlags.Union) ? (constraint as UnionType).origin : (constraint as IntersectionType); + if (!origin || !(origin.flags & TypeFlags.Intersection)) { + return; + } + const limitedConstraint = getIntersectionType((origin as IntersectionType).types.filter(t => t !== type.constraintType)); + return limitedConstraint !== neverType ? limitedConstraint : undefined; + } + function resolveReverseMappedTypeMembers(type: ReverseMappedType) { const indexInfo = getIndexInfoOfType(type.source, stringType); const modifiers = getMappedTypeModifiers(type.mappedType); @@ -13654,7 +13671,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional; const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray; const members = createSymbolTable(); + const limitedConstraint = getLimitedConstraint(type); for (const prop of getPropertiesOfType(type.source)) { + // In case of a reverse mapped type with an intersection constraint, if we were able to + // extract the filtering type literals we skip those properties that are not assignable to them, + // because the extra properties wouldn't get through the application of the mapped type anyway + if (limitedConstraint) { + const propertyNameType = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique); + if (!isTypeAssignableTo(propertyNameType, limitedConstraint)) { + continue; + } + } const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; inferredProp.declarations = prop.declarations; @@ -25665,9 +25692,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean { - if (constraintType.flags & TypeFlags.Union) { + if ((constraintType.flags & TypeFlags.Union) || (constraintType.flags & TypeFlags.Intersection)) { let result = false; - for (const type of (constraintType as UnionType).types) { + for (const type of (constraintType as (UnionType | IntersectionType)).types) { result = inferToMappedType(source, target, type) || result; } return result; diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt new file mode 100644 index 00000000000..ec7eab991b0 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt @@ -0,0 +1,225 @@ +reverseMappedTypeIntersectionConstraint.ts(19,7): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +reverseMappedTypeIntersectionConstraint.ts(32,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ entry: "foo"; states: { a: { entry: "foo"; }; }; }'. +reverseMappedTypeIntersectionConstraint.ts(43,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. +reverseMappedTypeIntersectionConstraint.ts(59,7): error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeIntersectionConstraint.ts(63,49): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeIntersectionConstraint.ts(69,7): error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. + Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeIntersectionConstraint.ts(74,36): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeIntersectionConstraint.ts(87,12): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeIntersectionConstraint.ts(98,12): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. +reverseMappedTypeIntersectionConstraint.ts(100,22): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; y: "foo"; }'. +reverseMappedTypeIntersectionConstraint.ts(113,67): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ prop: "foo"; nested: { prop: string; }; }'. +reverseMappedTypeIntersectionConstraint.ts(152,21): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. +reverseMappedTypeIntersectionConstraint.ts(164,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ types: { actors: { src: "str"; logic: () => any; }; }; invoke: { readonly src: "str"; }; }'. +reverseMappedTypeIntersectionConstraint.ts(171,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ invoke: { readonly src: "whatever"; }; }'. + + +==== reverseMappedTypeIntersectionConstraint.ts (14 errors) ==== + type StateConfig = { + entry?: TAction + states?: Record>; + }; + + type StateSchema = { + states?: Record; + }; + + declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, + >(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + + const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + ~~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6500 reverseMappedTypeIntersectionConstraint.ts:2:3: The expected type comes from property 'entry' which is declared here on type 'StateConfig<"foo">' + }, + }, + extra: 12, + }); + + const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ entry: "foo"; states: { a: { entry: "foo"; }; }; }'. + }); + + + // ----------------------------------------------------------------------------------------- + + const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + + const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + }); + + checked; + + // ----------------------------------------------------------------------------------------- + + interface Stuff { + field: number; + anotherField: string; + } + + function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + + doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. + + function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + + doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. + ]) + + // ----------------------------------------------------------------------------------------- + + type XNumber = { x: number } + + declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + + function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design + } + + foo({x: 1, y: 'foo'}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + + foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + + // ----------------------------------------------------------------------------------------- + + type NoErrWithOptProps = { x: number, y?: string } + + declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + + baz({x: 1}); + baz({x: 1, z: 123}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. + baz({x: 1, y: 'foo'}); + baz({x: 1, y: 'foo', z: 123}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; y: "foo"; }'. + + // ----------------------------------------------------------------------------------------- + + interface WithNestedProp { + prop: string; + nested: { + prop: string; + } + } + + declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + + const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ prop: "foo"; nested: { prop: string; }; }'. + + // ----------------------------------------------------------------------------------------- + + type IsLiteralString = string extends T ? false : true; + + type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + + interface ProvidedActor { + src: string; + logic: () => Promise; + } + + type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + + interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; + } + + type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never + } + + declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, + >(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + + const child = () => Promise.resolve("foo"); + ~~~~~~~ +!!! error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + + const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ types: { actors: { src: "str"; logic: () => any; }; }; invoke: { readonly src: "str"; }; }'. + }); + + const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ invoke: { readonly src: "whatever"; }; }'. + }); + \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js new file mode 100644 index 00000000000..a68576c793b --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js @@ -0,0 +1,260 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +//// [reverseMappedTypeIntersectionConstraint.ts] +type StateConfig = { + entry?: TAction + states?: Record>; +}; + +type StateSchema = { + states?: Record; +}; + +declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + +const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); + +const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); + +checked; + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; + anotherField: string; +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + } +} + +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + +function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design +} + +foo({x: 1, y: 'foo'}); + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + +baz({x: 1}); +baz({x: 1, z: 123}); +baz({x: 1, y: 'foo'}); +baz({x: 1, y: 'foo', z: 123}); + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; + nested: { + prop: string; + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + +interface ProvidedActor { + src: string; + logic: () => Promise; +} + +type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + +interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; +} + +type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + +const child = () => Promise.resolve("foo"); + +const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 +}); + +const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); + + +//// [reverseMappedTypeIntersectionConstraint.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); +var inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); +// ----------------------------------------------------------------------------------------- +var checkType = function () { return function (value) { return value; }; }; +var checked = checkType()({ + x: 1, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); +checked; +function doStuffWithStuff(s) { + if (Math.random() > 0.5) { + return s; + } + else { + return s; + } +} +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }); +function doStuffWithStuffArr(arr) { + if (Math.random() > 0.5) { + return arr; + } + else { + return arr; + } +} +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]); +function bar(props) { + return foo(props); // no error because lack of excess property check by design +} +foo({ x: 1, y: 'foo' }); +foo(__assign({ x: 1, y: 'foo' })); // no error because lack of excess property check by design +baz({ x: 1 }); +baz({ x: 1, z: 123 }); +baz({ x: 1, y: 'foo' }); +baz({ x: 1, y: 'foo', z: 123 }); +var wnp = withNestedProp({ prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +var child = function () { return Promise.resolve("foo"); }; +var config = createXMachine({ + types: {}, + invoke: { + src: "str", + }, + extra: 10 +}); +var config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols new file mode 100644 index 00000000000..12cb8664c84 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols @@ -0,0 +1,491 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +=== reverseMappedTypeIntersectionConstraint.ts === +type StateConfig = { +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + + entry?: TAction +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 44)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + + states?: Record>; +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 1, 17)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + +}; + +type StateSchema = { +>StateSchema : Symbol(StateSchema, Decl(reverseMappedTypeIntersectionConstraint.ts, 3, 2)) + + states?: Record; +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 5, 20)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>StateSchema : Symbol(StateSchema, Decl(reverseMappedTypeIntersectionConstraint.ts, 3, 2)) + +}; + +declare function createMachine< +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + TConfig extends StateConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) + + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) + +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 2)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 13)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 13)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) + +const inferredParams1 = createMachine({ +>inferredParams1 : Symbol(inferredParams1, Decl(reverseMappedTypeIntersectionConstraint.ts, 14, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 14, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 15, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeIntersectionConstraint.ts, 16, 11)) + + entry: "bar", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 17, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 20, 4)) + +}); + +const inferredParams2 = createMachine({ +>inferredParams2 : Symbol(inferredParams2, Decl(reverseMappedTypeIntersectionConstraint.ts, 24, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 24, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 25, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeIntersectionConstraint.ts, 26, 11)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 27, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 30, 4)) + +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType : Symbol(checkType, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 5)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>value : Symbol(value, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 41)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 51)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 51)) +>value : Symbol(value, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 41)) + +const checked = checkType<{x: number, y: string}>()({ +>checked : Symbol(checked, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 5)) +>checkType : Symbol(checkType, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 5)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 27)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 37)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 53)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 40, 17)) + + z: "z", // undesirable property z is *not* allowed +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 41, 9)) + +}); + +checked; +>checked : Symbol(checked, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 5)) + +// ----------------------------------------------------------------------------------------- + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) + + field: number; +>field : Symbol(Stuff.field, Decl(reverseMappedTypeIntersectionConstraint.ts, 49, 17)) + + anotherField: string; +>anotherField : Symbol(Stuff.anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 50, 18)) +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 52, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) + + if(Math.random() > 0.5) { +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return s as T +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) + + } else { + return s +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 52, 1)) +>field : Symbol(field, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 18)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 28)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 47)) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 61)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 54)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 54)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) + + if(Math.random() > 0.5) { +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return arr as T[] +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) + + } else { + return arr +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) + } +} + +doStuffWithStuffArr([ +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 61)) + + { field: 1, anotherField: 'a', extra: 123 }, +>field : Symbol(field, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 5)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 15)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 34)) + +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 16)) + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 40)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 49)) + +function bar(props: {x: number, y: string}) { +>bar : Symbol(bar, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 93)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 13)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 21)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 31)) + + return foo(props); // no error because lack of excess property check by design +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 13)) +} + +foo({x: 1, y: 'foo'}); +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 86, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 86, 10)) + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 9)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 14)) + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 26)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 37)) + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 50)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 59)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 59)) + +baz({x: 1}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 96, 5)) + +baz({x: 1, z: 123}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 97, 5)) +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 97, 10)) + +baz({x: 1, y: 'foo'}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 98, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 98, 10)) + +baz({x: 1, y: 'foo', z: 123}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 10)) +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 20)) + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) + + prop: string; +>prop : Symbol(WithNestedProp.prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 103, 26)) + + nested: { +>nested : Symbol(WithNestedProp.nested, Decl(reverseMappedTypeIntersectionConstraint.ts, 104, 15)) + + prop: string; +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 105, 11)) + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 108, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 58)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 67)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 67)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +>wnp : Symbol(wnp, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 5)) +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 108, 1)) +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 28)) +>nested : Symbol(nested, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 40)) +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 50)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 65)) + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 79)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 21)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 21)) + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } +>DeepWritable : Symbol(DeepWritable, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 73)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 61)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>DeepWritable : Symbol(DeepWritable, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 73)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 61)) + +interface ProvidedActor { +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + + src: string; +>src : Symbol(ProvidedActor.src, Decl(reverseMappedTypeIntersectionConstraint.ts, 120, 25)) + + logic: () => Promise; +>logic : Symbol(ProvidedActor.logic, Decl(reverseMappedTypeIntersectionConstraint.ts, 121, 14)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +} + +type DistributeActors = TActor extends { src: infer TSrc } +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeIntersectionConstraint.ts, 123, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 22)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 22)) +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 48)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 59)) + + ? { + src: TSrc; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 126, 5)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 59)) + } + : never; + +interface MachineConfig { +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + + types?: { +>types : Symbol(MachineConfig.types, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 55)) + + actors?: TActor; +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 132, 11)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + }; + invoke: IsLiteralString extends true +>invoke : Symbol(MachineConfig.invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 134, 4)) +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 79)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + ? DistributeActors +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeIntersectionConstraint.ts, 123, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + : { + src: string; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 137, 7)) + + }; +} + +type NoExtra = { +>NoExtra : Symbol(NoExtra, Decl(reverseMappedTypeIntersectionConstraint.ts, 140, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) + + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +} + +declare function createXMachine< +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + const TConfig extends MachineConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 147, 46)) + + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 147, 46)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>types : Symbol(types, Decl(reverseMappedTypeIntersectionConstraint.ts, 148, 50)) +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 148, 59)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 2)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 12)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 12)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) + +const child = () => Promise.resolve("foo"); +>child : Symbol(child, Decl(reverseMappedTypeIntersectionConstraint.ts, 151, 5)) + +const config = createXMachine({ +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 153, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + types: {} as { +>types : Symbol(types, Decl(reverseMappedTypeIntersectionConstraint.ts, 153, 31)) + + actors: { +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 154, 16)) + + src: "str"; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 155, 13)) + + logic: typeof child; +>logic : Symbol(logic, Decl(reverseMappedTypeIntersectionConstraint.ts, 156, 17)) +>child : Symbol(child, Decl(reverseMappedTypeIntersectionConstraint.ts, 151, 5)) + + }; + }, + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 159, 4)) + + src: "str", +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 160, 11)) + + }, + extra: 10 +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 162, 4)) + +}); + +const config2 = createXMachine({ +>config2 : Symbol(config2, Decl(reverseMappedTypeIntersectionConstraint.ts, 166, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 166, 32)) + + src: "whatever", +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 167, 11)) + + }, + extra: 10 +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 169, 4)) + +}); + diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types new file mode 100644 index 00000000000..43b568dd83d --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types @@ -0,0 +1,461 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +=== reverseMappedTypeIntersectionConstraint.ts === +type StateConfig = { +>StateConfig : StateConfig + + entry?: TAction +>entry : TAction | undefined + + states?: Record>; +>states : Record> | undefined + +}; + +type StateSchema = { +>StateSchema : { states?: Record | undefined; } + + states?: Record; +>states : Record | undefined + +}; + +declare function createMachine< +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] + + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; +>config : { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; } + +const inferredParams1 = createMachine({ +>inferredParams1 : ["foo", StateConfig<"foo">] +>createMachine({ entry: "foo", states: { a: { entry: "bar", }, }, extra: 12,}) : ["foo", StateConfig<"foo">] +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] +>{ entry: "foo", states: { a: { entry: "bar", }, }, extra: 12,} : { entry: "foo"; states: { a: { entry: "bar"; }; }; extra: number; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + states: { +>states : { a: { entry: "bar"; }; } +>{ a: { entry: "bar", }, } : { a: { entry: "bar"; }; } + + a: { +>a : { entry: "bar"; } +>{ entry: "bar", } : { entry: "bar"; } + + entry: "bar", +>entry : "bar" +>"bar" : "bar" + + }, + }, + extra: 12, +>extra : number +>12 : 12 + +}); + +const inferredParams2 = createMachine({ +>inferredParams2 : ["foo", { entry: "foo"; states: { a: { entry: "foo"; }; }; }] +>createMachine({ entry: "foo", states: { a: { entry: "foo", }, }, extra: 12,}) : ["foo", { entry: "foo"; states: { a: { entry: "foo"; }; }; }] +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] +>{ entry: "foo", states: { a: { entry: "foo", }, }, extra: 12,} : { entry: "foo"; states: { a: { entry: "foo"; }; }; extra: number; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + states: { +>states : { a: { entry: "foo"; }; } +>{ a: { entry: "foo", }, } : { a: { entry: "foo"; }; } + + a: { +>a : { entry: "foo"; } +>{ entry: "foo", } : { entry: "foo"; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + }, + }, + extra: 12, +>extra : number +>12 : 12 + +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>() => (value: { [K in keyof U & keyof T]: U[K] }) => value : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>(value: { [K in keyof U & keyof T]: U[K] }) => value : (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } + +const checked = checkType<{x: number, y: string}>()({ +>checked : { x: number; y: "y"; } +>checkType<{x: number, y: string}>()({ x: 1 as number, y: "y", z: "z", // undesirable property z is *not* allowed}) : { x: number; y: "y"; } +>checkType<{x: number, y: string}>() : (value: { [K in keyof U & ("x" | "y")]: U[K]; }) => { [K in keyof U & ("x" | "y")]: U[K]; } +>checkType : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>x : number +>y : string +>{ x: 1 as number, y: "y", z: "z", // undesirable property z is *not* allowed} : { x: number; y: "y"; z: string; } + + x: 1 as number, +>x : number +>1 as number : number +>1 : 1 + + y: "y", +>y : "y" +>"y" : "y" + + z: "z", // undesirable property z is *not* allowed +>z : string +>"z" : "z" + +}); + +checked; +>checked : { x: number; y: "y"; } + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; +>field : number + + anotherField: string; +>anotherField : string +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { +>doStuffWithStuff : (s: { [K in keyof T & keyof Stuff]: T[K]; }) => T +>s : { [K in keyof T & keyof Stuff]: T[K]; } + + if(Math.random() > 0.5) { +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + return s as T +>s as T : T +>s : { [K in keyof T & keyof Stuff]: T[K]; } + + } else { + return s +>s : { [K in keyof T & keyof Stuff]: T[K]; } + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) +>doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) : { field: 1; anotherField: "a"; } +>doStuffWithStuff : (s: { [K in keyof T & keyof Stuff]: T[K]; }) => T +>{ field: 1, anotherField: 'a', extra: 123 } : { field: 1; anotherField: "a"; extra: number; } +>field : 1 +>1 : 1 +>anotherField : "a" +>'a' : "a" +>extra : number +>123 : 123 + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { +>doStuffWithStuffArr : (arr: { [K in keyof T & keyof Stuff]: T[K]; }[]) => T[] +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + + if(Math.random() > 0.5) { +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + return arr as T[] +>arr as T[] : T[] +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + + } else { + return arr +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + } +} + +doStuffWithStuffArr([ +>doStuffWithStuffArr([ { field: 1, anotherField: 'a', extra: 123 },]) : { field: 1; anotherField: "a"; }[] +>doStuffWithStuffArr : (arr: { [K in keyof T & keyof Stuff]: T[K]; }[]) => T[] +>[ { field: 1, anotherField: 'a', extra: 123 },] : { field: 1; anotherField: "a"; extra: number; }[] + + { field: 1, anotherField: 'a', extra: 123 }, +>{ field: 1, anotherField: 'a', extra: 123 } : { field: 1; anotherField: "a"; extra: number; } +>field : 1 +>1 : 1 +>anotherField : "a" +>'a' : "a" +>extra : number +>123 : 123 + +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } +>XNumber : { x: number; } +>x : number + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>props : { [K in keyof T & "x"]: T[K]; } + +function bar(props: {x: number, y: string}) { +>bar : (props: { x: number; y: string;}) => void +>props : { x: number; y: string; } +>x : number +>y : string + + return foo(props); // no error because lack of excess property check by design +>foo(props) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>props : { x: number; y: string; } +} + +foo({x: 1, y: 'foo'}); +>foo({x: 1, y: 'foo'}) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design +>foo({...{x: 1, y: 'foo'}}) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>{...{x: 1, y: 'foo'}} : { x: 1; y: string; } +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } +>NoErrWithOptProps : { x: number; y?: string | undefined; } +>x : number +>y : string | undefined + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>props : { [K in keyof T & keyof NoErrWithOptProps]: T[K]; } + +baz({x: 1}); +>baz({x: 1}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1} : { x: 1; } +>x : 1 +>1 : 1 + +baz({x: 1, z: 123}); +>baz({x: 1, z: 123}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, z: 123} : { x: 1; z: number; } +>x : 1 +>1 : 1 +>z : number +>123 : 123 + +baz({x: 1, y: 'foo'}); +>baz({x: 1, y: 'foo'}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, y: 'foo'} : { x: 1; y: "foo"; } +>x : 1 +>1 : 1 +>y : "foo" +>'foo' : "foo" + +baz({x: 1, y: 'foo', z: 123}); +>baz({x: 1, y: 'foo', z: 123}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, y: 'foo', z: 123} : { x: 1; y: "foo"; z: number; } +>x : 1 +>1 : 1 +>y : "foo" +>'foo' : "foo" +>z : number +>123 : 123 + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; +>prop : string + + nested: { +>nested : { prop: string; } + + prop: string; +>prop : string + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; +>withNestedProp : (props: { [K in keyof T & keyof WithNestedProp]: T[K]; }) => T +>props : { [K in keyof T & keyof WithNestedProp]: T[K]; } + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +>wnp : { prop: "foo"; nested: { prop: string; }; } +>withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }) : { prop: "foo"; nested: { prop: string; }; } +>withNestedProp : (props: { [K in keyof T & keyof WithNestedProp]: T[K]; }) => T +>{prop: 'foo', nested: { prop: 'bar' }, extra: 10 } : { prop: "foo"; nested: { prop: string; }; extra: number; } +>prop : "foo" +>'foo' : "foo" +>nested : { prop: string; } +>{ prop: 'bar' } : { prop: string; } +>prop : string +>'bar' : "bar" +>extra : number +>10 : 10 + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; +>IsLiteralString : IsLiteralString +>false : false +>true : true + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } +>DeepWritable : DeepWritable + +interface ProvidedActor { + src: string; +>src : string + + logic: () => Promise; +>logic : () => Promise +} + +type DistributeActors = TActor extends { src: infer TSrc } +>DistributeActors : DistributeActors +>src : TSrc + + ? { + src: TSrc; +>src : TSrc + } + : never; + +interface MachineConfig { + types?: { +>types : { actors?: TActor | undefined; } | undefined + + actors?: TActor; +>actors : TActor | undefined + + }; + invoke: IsLiteralString extends true +>invoke : IsLiteralString extends true ? DistributeActors : { src: string; } +>true : true + + ? DistributeActors + : { + src: string; +>src : string + + }; +} + +type NoExtra = { +>NoExtra : NoExtra + + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor;}; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig + + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>types : { actors: ProvidedActor; } +>actors : ProvidedActor + +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; +>config : { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; } + +const child = () => Promise.resolve("foo"); +>child : () => any +>() => Promise.resolve("foo") : () => any +>Promise.resolve("foo") : any +>Promise.resolve : any +>Promise : any +>resolve : any +>"foo" : "foo" + +const config = createXMachine({ +>config : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { readonly src: "str"; }; } +>createXMachine({ types: {} as { actors: { src: "str"; logic: typeof child; }; }, invoke: { src: "str", }, extra: 10}) : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { readonly src: "str"; }; } +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig +>{ types: {} as { actors: { src: "str"; logic: typeof child; }; }, invoke: { src: "str", }, extra: 10} : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { src: "str"; }; extra: number; } + + types: {} as { +>types : { actors: { src: "str"; logic: typeof child;}; } +>{} as { actors: { src: "str"; logic: typeof child; }; } : { actors: { src: "str"; logic: typeof child;}; } +>{} : {} + + actors: { +>actors : { src: "str"; logic: typeof child; } + + src: "str"; +>src : "str" + + logic: typeof child; +>logic : () => any +>child : () => any + + }; + }, + invoke: { +>invoke : { src: "str"; } +>{ src: "str", } : { src: "str"; } + + src: "str", +>src : "str" +>"str" : "str" + + }, + extra: 10 +>extra : number +>10 : 10 + +}); + +const config2 = createXMachine({ +>config2 : { invoke: { readonly src: "whatever"; }; } +>createXMachine({ invoke: { src: "whatever", }, extra: 10}) : { invoke: { readonly src: "whatever"; }; } +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig +>{ invoke: { src: "whatever", }, extra: 10} : { invoke: { src: "whatever"; }; extra: number; } + + invoke: { +>invoke : { src: "whatever"; } +>{ src: "whatever", } : { src: "whatever"; } + + src: "whatever", +>src : "whatever" +>"whatever" : "whatever" + + }, + extra: 10 +>extra : number +>10 : 10 + +}); + diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt new file mode 100644 index 00000000000..dc6dc8fa3a3 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt @@ -0,0 +1,24 @@ +reverseMappedTypeLimitedConstraint.ts(5,13): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeLimitedConstraint.ts(14,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + + +==== reverseMappedTypeLimitedConstraint.ts (2 errors) ==== + type XNumber_ = { x: number } + + declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + + foo_({x: 1, y: 'foo'}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + + // ----------------------------------------------------------------------------------------- + + const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + + const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + }); \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js new file mode 100644 index 00000000000..0be7aa8d6a4 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +//// [reverseMappedTypeLimitedConstraint.ts] +type XNumber_ = { x: number } + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + +foo_({x: 1, y: 'foo'}); + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", +}); + +//// [reverseMappedTypeLimitedConstraint.js] +foo_({ x: 1, y: 'foo' }); +// ----------------------------------------------------------------------------------------- +var checkType_ = function () { return function (value) { return value; }; }; +var checked_ = checkType_()({ + x: 1, + y: "y", + z: "z", +}); diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols new file mode 100644 index 00000000000..5c815072784 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +=== reverseMappedTypeLimitedConstraint.ts === +type XNumber_ = { x: number } +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 17)) + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; +>foo_ : Symbol(foo_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>props : Symbol(props, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 42)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 51)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 51)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) + +foo_({x: 1, y: 'foo'}); +>foo_ : Symbol(foo_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 29)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 4, 6)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 4, 11)) + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType_ : Symbol(checkType_, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 5)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 42)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 52)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 52)) +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 42)) + +const checked_ = checkType_<{x: number, y: string}>()({ +>checked_ : Symbol(checked_, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 5)) +>checkType_ : Symbol(checkType_, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 5)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 29)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 39)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 55)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 11, 17)) + + z: "z", +>z : Symbol(z, Decl(reverseMappedTypeLimitedConstraint.ts, 12, 9)) + +}); diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types new file mode 100644 index 00000000000..821d7685fcc --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types @@ -0,0 +1,52 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +=== reverseMappedTypeLimitedConstraint.ts === +type XNumber_ = { x: number } +>XNumber_ : { x: number; } +>x : number + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; +>foo_ : (props: { [K in keyof T & "x"]: T[K]; }) => T +>props : { [K in keyof T & "x"]: T[K]; } + +foo_({x: 1, y: 'foo'}); +>foo_({x: 1, y: 'foo'}) : { x: 1; } +>foo_ : (props: { [K in keyof T & "x"]: T[K]; }) => T +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType_ : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>() => (value: { [K in keyof U & keyof T]: U[K] }) => value : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>(value: { [K in keyof U & keyof T]: U[K] }) => value : (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } + +const checked_ = checkType_<{x: number, y: string}>()({ +>checked_ : { x: number; y: "y"; } +>checkType_<{x: number, y: string}>()({ x: 1 as number, y: "y", z: "z",}) : { x: number; y: "y"; } +>checkType_<{x: number, y: string}>() : (value: { [K in keyof U & ("x" | "y")]: U[K]; }) => { [K in keyof U & ("x" | "y")]: U[K]; } +>checkType_ : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>x : number +>y : string +>{ x: 1 as number, y: "y", z: "z",} : { x: number; y: "y"; z: string; } + + x: 1 as number, +>x : number +>1 as number : number +>1 : 1 + + y: "y", +>y : "y" +>"y" : "y" + + z: "z", +>z : string +>"z" : "z" + +}); diff --git a/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts b/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts new file mode 100644 index 00000000000..e5655497911 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts @@ -0,0 +1,174 @@ +// @strict: true + +type StateConfig = { + entry?: TAction + states?: Record>; +}; + +type StateSchema = { + states?: Record; +}; + +declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + +const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); + +const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); + +checked; + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; + anotherField: string; +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + } +} + +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + +function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design +} + +foo({x: 1, y: 'foo'}); + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + +baz({x: 1}); +baz({x: 1, z: 123}); +baz({x: 1, y: 'foo'}); +baz({x: 1, y: 'foo', z: 123}); + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; + nested: { + prop: string; + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + +interface ProvidedActor { + src: string; + logic: () => Promise; +} + +type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + +interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; +} + +type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + +const child = () => Promise.resolve("foo"); + +const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 +}); + +const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); diff --git a/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts b/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts new file mode 100644 index 00000000000..7618ae65046 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts @@ -0,0 +1,15 @@ +type XNumber_ = { x: number } + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + +foo_({x: 1, y: 'foo'}); + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", +}); \ No newline at end of file From 8d1fa440dd5ad547e836abcca45ccc94e81f1fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 30 Nov 2023 20:24:04 +0100 Subject: [PATCH 03/12] Defer processing of nested generic calls that return constructor types (#54813) Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 10 ++- ...ericNestedCallReturningConstructor.symbols | 72 +++++++++++++++++++ ...enericNestedCallReturningConstructor.types | 63 ++++++++++++++++ ...ceGenericNestedCallReturningConstructor.ts | 28 ++++++++ 4 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols create mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types create mode 100644 tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea86fc74de3..8f1b6918320 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34776,7 +34776,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // use the resolvingSignature singleton to indicate that we deferred processing. This result will be // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and // from which we never make inferences). - if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -34789,8 +34789,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunction(signature: Signature) { - return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); + function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) { + if (!signature.typeParameters) { + return false; + } + const returnType = getReturnTypeOfSignature(signature); + return isFunctionType(returnType) || isConstructorType(returnType); } /** diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols new file mode 100644 index 00000000000..03e0bcb9f16 --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface Action { +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) + + new (ctx: TContext): void; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) +} + +declare class AssignAction { +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) + + constructor(ctx: TContext); +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 14)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) +} + +declare function assign( +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) + + assigner: (ctx: TContext) => void +>assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 34)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 13)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) + +): { + new (ctx: TContext): AssignAction; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 11, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +} + +declare function createMachine(config: { +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) +>config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 41)) + + context: TContext; +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 50)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) + + entry: Action; +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 20)) +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) + +}): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) + + context: { count: 0 }, +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 19, 15)) +>count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 12)) + + entry: assign((ctx) => { +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 24)) +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) + + ctx // { count: number } +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) + + }), +}); + diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types new file mode 100644 index 00000000000..ce6d09b4d32 --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface Action { + new (ctx: TContext): void; +>ctx : TContext +} + +declare class AssignAction { +>AssignAction : AssignAction + + constructor(ctx: TContext); +>ctx : TContext +} + +declare function assign( +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction + + assigner: (ctx: TContext) => void +>assigner : (ctx: TContext) => void +>ctx : TContext + +): { + new (ctx: TContext): AssignAction; +>ctx : TContext +} + +declare function createMachine(config: { +>createMachine : (config: { context: TContext; entry: Action;}) => void +>config : { context: TContext; entry: Action; } + + context: TContext; +>context : TContext + + entry: Action; +>entry : Action + +}): void; + +createMachine({ +>createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void +>createMachine : (config: { context: TContext; entry: Action; }) => void +>{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: new (ctx: { count: number; }) => AssignAction<{ count: number; }>; } + + context: { count: 0 }, +>context : { count: number; } +>{ count: 0 } : { count: number; } +>count : number +>0 : 0 + + entry: assign((ctx) => { +>entry : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign((ctx) => { ctx // { count: number } }) : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction +>(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void +>ctx : { count: number; } + + ctx // { count: number } +>ctx : { count: number; } + + }), +}); + diff --git a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts new file mode 100644 index 00000000000..8c1ea320962 --- /dev/null +++ b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noEmit: true + +interface Action { + new (ctx: TContext): void; +} + +declare class AssignAction { + constructor(ctx: TContext); +} + +declare function assign( + assigner: (ctx: TContext) => void +): { + new (ctx: TContext): AssignAction; +} + +declare function createMachine(config: { + context: TContext; + entry: Action; +}): void; + +createMachine({ + context: { count: 0 }, + entry: assign((ctx) => { + ctx // { count: number } + }), +}); From fd74874733a20e1f433cc37229152eddea81c1d1 Mon Sep 17 00:00:00 2001 From: Nil Admirari <50202386+nihil-admirari@users.noreply.github.com> Date: Thu, 30 Nov 2023 21:51:08 +0000 Subject: [PATCH 04/12] String#matchAll should return iterable of RegExpExecArray (fixes #36788) (#55565) Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/lib/es2020.string.d.ts | 2 +- .../baselines/reference/stringMatchAll.types | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/es2020.string.d.ts b/src/lib/es2020.string.d.ts index 1602ac7b10f..bc7cf1ad5f7 100644 --- a/src/lib/es2020.string.d.ts +++ b/src/lib/es2020.string.d.ts @@ -6,7 +6,7 @@ interface String { * containing the results of that search. * @param regexp A variable name or string literal containing the regular expression pattern and flags. */ - matchAll(regexp: RegExp): IterableIterator; + matchAll(regexp: RegExp): IterableIterator; /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */ toLocaleLowerCase(locales?: Intl.LocalesArgument): string; diff --git a/tests/baselines/reference/stringMatchAll.types b/tests/baselines/reference/stringMatchAll.types index 59c112f5016..9386da13c84 100644 --- a/tests/baselines/reference/stringMatchAll.types +++ b/tests/baselines/reference/stringMatchAll.types @@ -2,23 +2,23 @@ === stringMatchAll.ts === const matches = "matchAll".matchAll(/\w/g); ->matches : IterableIterator ->"matchAll".matchAll(/\w/g) : IterableIterator ->"matchAll".matchAll : (regexp: RegExp) => IterableIterator +>matches : IterableIterator +>"matchAll".matchAll(/\w/g) : IterableIterator +>"matchAll".matchAll : (regexp: RegExp) => IterableIterator >"matchAll" : "matchAll" ->matchAll : (regexp: RegExp) => IterableIterator +>matchAll : (regexp: RegExp) => IterableIterator >/\w/g : RegExp const array = [...matches]; ->array : RegExpMatchArray[] ->[...matches] : RegExpMatchArray[] ->...matches : RegExpMatchArray ->matches : IterableIterator +>array : RegExpExecArray[] +>[...matches] : RegExpExecArray[] +>...matches : RegExpExecArray +>matches : IterableIterator const { index, input } = array[0]; >index : number >input : string ->array[0] : RegExpMatchArray ->array : RegExpMatchArray[] +>array[0] : RegExpExecArray +>array : RegExpExecArray[] >0 : 0 From 30f3ce7b517714f6c33ddb4db9a0c109ed8a1d5d Mon Sep 17 00:00:00 2001 From: Mitar Date: Thu, 30 Nov 2023 14:57:08 -0800 Subject: [PATCH 05/12] Do not suggest lib.dom.d.ts (#56617) --- .github/ISSUE_TEMPLATE/lib_change.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/lib_change.yml b/.github/ISSUE_TEMPLATE/lib_change.yml index 8d965d56722..21312c88e12 100644 --- a/.github/ISSUE_TEMPLATE/lib_change.yml +++ b/.github/ISSUE_TEMPLATE/lib_change.yml @@ -1,5 +1,5 @@ name: 'Library change' -description: 'Fix or improve issues with built-in type definitions like `lib.dom.d.ts`, `lib.es6.d.ts`, etc.' +description: 'Fix or improve issues with built-in type definitions like `lib.es6.d.ts`, etc.' body: - type: markdown attributes: From 6edfef8c0d4535eb8fdb83405f57dabec9b8166f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 30 Nov 2023 23:57:52 +0100 Subject: [PATCH 06/12] Fixed an issue with reverse mapped types inference when single type variable is left after inferring from matching types (#55941) Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 2 +- .../reverseMappedUnionInference.symbols | 172 ++++++++++++++++++ .../reverseMappedUnionInference.types | 148 +++++++++++++++ .../compiler/reverseMappedUnionInference.ts | 59 ++++++ 4 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/reverseMappedUnionInference.symbols create mode 100644 tests/baselines/reference/reverseMappedUnionInference.types create mode 100644 tests/cases/compiler/reverseMappedUnionInference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8f1b6918320..289a98a4295 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25354,7 +25354,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { target = getIntersectionType(targets); } } - else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) { + if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) { target = getActualTypeVariable(target); } if (target.flags & TypeFlags.TypeVariable) { diff --git a/tests/baselines/reference/reverseMappedUnionInference.symbols b/tests/baselines/reference/reverseMappedUnionInference.symbols new file mode 100644 index 00000000000..ec09965565d --- /dev/null +++ b/tests/baselines/reference/reverseMappedUnionInference.symbols @@ -0,0 +1,172 @@ +//// [tests/cases/compiler/reverseMappedUnionInference.ts] //// + +=== reverseMappedUnionInference.ts === +interface AnyExtractor { +>AnyExtractor : Symbol(AnyExtractor, Decl(reverseMappedUnionInference.ts, 0, 0)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 0, 23)) + + matches: (node: any) => boolean; +>matches : Symbol(AnyExtractor.matches, Decl(reverseMappedUnionInference.ts, 0, 32)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 1, 12)) + + extract: (node: any) => Result | undefined; +>extract : Symbol(AnyExtractor.extract, Decl(reverseMappedUnionInference.ts, 1, 34)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 2, 12)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 0, 23)) +} + +interface Extractor { +>Extractor : Symbol(Extractor, Decl(reverseMappedUnionInference.ts, 3, 1)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 5, 20)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 5, 22)) + + matches: (node: unknown) => node is T; +>matches : Symbol(Extractor.matches, Decl(reverseMappedUnionInference.ts, 5, 32)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 6, 12)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 6, 12)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 5, 20)) + + extract: (node: T) => Result | undefined; +>extract : Symbol(Extractor.extract, Decl(reverseMappedUnionInference.ts, 6, 40)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 7, 12)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 5, 20)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 5, 22)) +} + +declare function createExtractor(params: { +>createExtractor : Symbol(createExtractor, Decl(reverseMappedUnionInference.ts, 8, 1)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 10, 33)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 10, 35)) +>params : Symbol(params, Decl(reverseMappedUnionInference.ts, 10, 44)) + + matcher: (node: unknown) => node is T; +>matcher : Symbol(matcher, Decl(reverseMappedUnionInference.ts, 10, 53)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 11, 12)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 11, 12)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 10, 33)) + + extract: (node: T) => Result; +>extract : Symbol(extract, Decl(reverseMappedUnionInference.ts, 11, 40)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 12, 12)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 10, 33)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 10, 35)) + +}): Extractor; +>Extractor : Symbol(Extractor, Decl(reverseMappedUnionInference.ts, 3, 1)) +>T : Symbol(T, Decl(reverseMappedUnionInference.ts, 10, 33)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 10, 35)) + +interface Identifier { +>Identifier : Symbol(Identifier, Decl(reverseMappedUnionInference.ts, 13, 25)) + + kind: "identifier"; +>kind : Symbol(Identifier.kind, Decl(reverseMappedUnionInference.ts, 15, 22)) + + name: string; +>name : Symbol(Identifier.name, Decl(reverseMappedUnionInference.ts, 16, 21)) +} + +declare function isIdentifier(node: unknown): node is Identifier; +>isIdentifier : Symbol(isIdentifier, Decl(reverseMappedUnionInference.ts, 18, 1)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 20, 30)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 20, 30)) +>Identifier : Symbol(Identifier, Decl(reverseMappedUnionInference.ts, 13, 25)) + +const identifierExtractor = createExtractor({ +>identifierExtractor : Symbol(identifierExtractor, Decl(reverseMappedUnionInference.ts, 22, 5)) +>createExtractor : Symbol(createExtractor, Decl(reverseMappedUnionInference.ts, 8, 1)) + + matcher: isIdentifier, +>matcher : Symbol(matcher, Decl(reverseMappedUnionInference.ts, 22, 45)) +>isIdentifier : Symbol(isIdentifier, Decl(reverseMappedUnionInference.ts, 18, 1)) + + extract: (node) => { +>extract : Symbol(extract, Decl(reverseMappedUnionInference.ts, 23, 24)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 24, 12)) + + return { + node, +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 25, 12)) + + kind: "identifier" as const, +>kind : Symbol(kind, Decl(reverseMappedUnionInference.ts, 26, 11)) +>const : Symbol(const) + + value: node.name, +>value : Symbol(value, Decl(reverseMappedUnionInference.ts, 27, 34)) +>node.name : Symbol(Identifier.name, Decl(reverseMappedUnionInference.ts, 16, 21)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 24, 12)) +>name : Symbol(Identifier.name, Decl(reverseMappedUnionInference.ts, 16, 21)) + + }; + }, +}); + +interface StringLiteral { +>StringLiteral : Symbol(StringLiteral, Decl(reverseMappedUnionInference.ts, 31, 3)) + + kind: "stringLiteral"; +>kind : Symbol(StringLiteral.kind, Decl(reverseMappedUnionInference.ts, 33, 25)) + + value: string; +>value : Symbol(StringLiteral.value, Decl(reverseMappedUnionInference.ts, 34, 24)) +} + +declare function isStringLiteral(node: unknown): node is StringLiteral; +>isStringLiteral : Symbol(isStringLiteral, Decl(reverseMappedUnionInference.ts, 36, 1)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 38, 33)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 38, 33)) +>StringLiteral : Symbol(StringLiteral, Decl(reverseMappedUnionInference.ts, 31, 3)) + +const stringExtractor = createExtractor({ +>stringExtractor : Symbol(stringExtractor, Decl(reverseMappedUnionInference.ts, 40, 5)) +>createExtractor : Symbol(createExtractor, Decl(reverseMappedUnionInference.ts, 8, 1)) + + matcher: isStringLiteral, +>matcher : Symbol(matcher, Decl(reverseMappedUnionInference.ts, 40, 41)) +>isStringLiteral : Symbol(isStringLiteral, Decl(reverseMappedUnionInference.ts, 36, 1)) + + extract: (node) => { +>extract : Symbol(extract, Decl(reverseMappedUnionInference.ts, 41, 27)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 42, 12)) + + return { + node, +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 43, 12)) + + kind: "string" as const, +>kind : Symbol(kind, Decl(reverseMappedUnionInference.ts, 44, 11)) +>const : Symbol(const) + + value: node.value, +>value : Symbol(value, Decl(reverseMappedUnionInference.ts, 45, 30)) +>node.value : Symbol(StringLiteral.value, Decl(reverseMappedUnionInference.ts, 34, 24)) +>node : Symbol(node, Decl(reverseMappedUnionInference.ts, 42, 12)) +>value : Symbol(StringLiteral.value, Decl(reverseMappedUnionInference.ts, 34, 24)) + + }; + }, +}); + +declare function unionType(parsers: { +>unionType : Symbol(unionType, Decl(reverseMappedUnionInference.ts, 49, 3)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 51, 27)) +>parsers : Symbol(parsers, Decl(reverseMappedUnionInference.ts, 51, 62)) + + [K in keyof Result]: AnyExtractor; +>K : Symbol(K, Decl(reverseMappedUnionInference.ts, 52, 3)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 51, 27)) +>AnyExtractor : Symbol(AnyExtractor, Decl(reverseMappedUnionInference.ts, 0, 0)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 51, 27)) +>K : Symbol(K, Decl(reverseMappedUnionInference.ts, 52, 3)) + +}): AnyExtractor; +>AnyExtractor : Symbol(AnyExtractor, Decl(reverseMappedUnionInference.ts, 0, 0)) +>Result : Symbol(Result, Decl(reverseMappedUnionInference.ts, 51, 27)) + +const myUnion = unionType([identifierExtractor, stringExtractor]); +>myUnion : Symbol(myUnion, Decl(reverseMappedUnionInference.ts, 55, 5)) +>unionType : Symbol(unionType, Decl(reverseMappedUnionInference.ts, 49, 3)) +>identifierExtractor : Symbol(identifierExtractor, Decl(reverseMappedUnionInference.ts, 22, 5)) +>stringExtractor : Symbol(stringExtractor, Decl(reverseMappedUnionInference.ts, 40, 5)) + diff --git a/tests/baselines/reference/reverseMappedUnionInference.types b/tests/baselines/reference/reverseMappedUnionInference.types new file mode 100644 index 00000000000..0ce2b95184f --- /dev/null +++ b/tests/baselines/reference/reverseMappedUnionInference.types @@ -0,0 +1,148 @@ +//// [tests/cases/compiler/reverseMappedUnionInference.ts] //// + +=== reverseMappedUnionInference.ts === +interface AnyExtractor { + matches: (node: any) => boolean; +>matches : (node: any) => boolean +>node : any + + extract: (node: any) => Result | undefined; +>extract : (node: any) => Result | undefined +>node : any +} + +interface Extractor { + matches: (node: unknown) => node is T; +>matches : (node: unknown) => node is T +>node : unknown + + extract: (node: T) => Result | undefined; +>extract : (node: T) => Result | undefined +>node : T +} + +declare function createExtractor(params: { +>createExtractor : (params: { matcher: (node: unknown) => node is T; extract: (node: T) => Result; }) => Extractor +>params : { matcher: (node: unknown) => node is T; extract: (node: T) => Result; } + + matcher: (node: unknown) => node is T; +>matcher : (node: unknown) => node is T +>node : unknown + + extract: (node: T) => Result; +>extract : (node: T) => Result +>node : T + +}): Extractor; + +interface Identifier { + kind: "identifier"; +>kind : "identifier" + + name: string; +>name : string +} + +declare function isIdentifier(node: unknown): node is Identifier; +>isIdentifier : (node: unknown) => node is Identifier +>node : unknown + +const identifierExtractor = createExtractor({ +>identifierExtractor : Extractor +>createExtractor({ matcher: isIdentifier, extract: (node) => { return { node, kind: "identifier" as const, value: node.name, }; },}) : Extractor +>createExtractor : (params: { matcher: (node: unknown) => node is T; extract: (node: T) => Result; }) => Extractor +>{ matcher: isIdentifier, extract: (node) => { return { node, kind: "identifier" as const, value: node.name, }; },} : { matcher: (node: unknown) => node is Identifier; extract: (node: Identifier) => { node: Identifier; kind: "identifier"; value: string; }; } + + matcher: isIdentifier, +>matcher : (node: unknown) => node is Identifier +>isIdentifier : (node: unknown) => node is Identifier + + extract: (node) => { +>extract : (node: Identifier) => { node: Identifier; kind: "identifier"; value: string; } +>(node) => { return { node, kind: "identifier" as const, value: node.name, }; } : (node: Identifier) => { node: Identifier; kind: "identifier"; value: string; } +>node : Identifier + + return { +>{ node, kind: "identifier" as const, value: node.name, } : { node: Identifier; kind: "identifier"; value: string; } + + node, +>node : Identifier + + kind: "identifier" as const, +>kind : "identifier" +>"identifier" as const : "identifier" +>"identifier" : "identifier" + + value: node.name, +>value : string +>node.name : string +>node : Identifier +>name : string + + }; + }, +}); + +interface StringLiteral { + kind: "stringLiteral"; +>kind : "stringLiteral" + + value: string; +>value : string +} + +declare function isStringLiteral(node: unknown): node is StringLiteral; +>isStringLiteral : (node: unknown) => node is StringLiteral +>node : unknown + +const stringExtractor = createExtractor({ +>stringExtractor : Extractor +>createExtractor({ matcher: isStringLiteral, extract: (node) => { return { node, kind: "string" as const, value: node.value, }; },}) : Extractor +>createExtractor : (params: { matcher: (node: unknown) => node is T; extract: (node: T) => Result; }) => Extractor +>{ matcher: isStringLiteral, extract: (node) => { return { node, kind: "string" as const, value: node.value, }; },} : { matcher: (node: unknown) => node is StringLiteral; extract: (node: StringLiteral) => { node: StringLiteral; kind: "string"; value: string; }; } + + matcher: isStringLiteral, +>matcher : (node: unknown) => node is StringLiteral +>isStringLiteral : (node: unknown) => node is StringLiteral + + extract: (node) => { +>extract : (node: StringLiteral) => { node: StringLiteral; kind: "string"; value: string; } +>(node) => { return { node, kind: "string" as const, value: node.value, }; } : (node: StringLiteral) => { node: StringLiteral; kind: "string"; value: string; } +>node : StringLiteral + + return { +>{ node, kind: "string" as const, value: node.value, } : { node: StringLiteral; kind: "string"; value: string; } + + node, +>node : StringLiteral + + kind: "string" as const, +>kind : "string" +>"string" as const : "string" +>"string" : "string" + + value: node.value, +>value : string +>node.value : string +>node : StringLiteral +>value : string + + }; + }, +}); + +declare function unionType(parsers: { +>unionType : (parsers: { [K in keyof Result]: AnyExtractor; }) => AnyExtractor +>parsers : { [K in keyof Result]: AnyExtractor; } + + [K in keyof Result]: AnyExtractor; +}): AnyExtractor; + +const myUnion = unionType([identifierExtractor, stringExtractor]); +>myUnion : AnyExtractor<{ node: Identifier; kind: "identifier"; value: string; } | { node: StringLiteral; kind: "string"; value: string; }> +>unionType([identifierExtractor, stringExtractor]) : AnyExtractor<{ node: Identifier; kind: "identifier"; value: string; } | { node: StringLiteral; kind: "string"; value: string; }> +>unionType : (parsers: { [K in keyof Result]: AnyExtractor; }) => AnyExtractor +>[identifierExtractor, stringExtractor] : (Extractor | Extractor)[] +>identifierExtractor : Extractor +>stringExtractor : Extractor + diff --git a/tests/cases/compiler/reverseMappedUnionInference.ts b/tests/cases/compiler/reverseMappedUnionInference.ts new file mode 100644 index 00000000000..0f1ffc1c347 --- /dev/null +++ b/tests/cases/compiler/reverseMappedUnionInference.ts @@ -0,0 +1,59 @@ +// @strict: true +// @noEmit: true + +interface AnyExtractor { + matches: (node: any) => boolean; + extract: (node: any) => Result | undefined; +} + +interface Extractor { + matches: (node: unknown) => node is T; + extract: (node: T) => Result | undefined; +} + +declare function createExtractor(params: { + matcher: (node: unknown) => node is T; + extract: (node: T) => Result; +}): Extractor; + +interface Identifier { + kind: "identifier"; + name: string; +} + +declare function isIdentifier(node: unknown): node is Identifier; + +const identifierExtractor = createExtractor({ + matcher: isIdentifier, + extract: (node) => { + return { + node, + kind: "identifier" as const, + value: node.name, + }; + }, +}); + +interface StringLiteral { + kind: "stringLiteral"; + value: string; +} + +declare function isStringLiteral(node: unknown): node is StringLiteral; + +const stringExtractor = createExtractor({ + matcher: isStringLiteral, + extract: (node) => { + return { + node, + kind: "string" as const, + value: node.value, + }; + }, +}); + +declare function unionType(parsers: { + [K in keyof Result]: AnyExtractor; +}): AnyExtractor; + +const myUnion = unionType([identifierExtractor, stringExtractor]); From 5bc66177388247d3e270653f94d82a8dabd56d69 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 30 Nov 2023 17:21:41 -0800 Subject: [PATCH 07/12] Transpile jsdoc parsing mode (#56627) --- src/services/transpile.ts | 3 ++- tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 9637387afa0..0b708e62826 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -36,6 +36,7 @@ export interface TranspileOptions { moduleName?: string; renamedDependencies?: MapLike; transformers?: CustomTransformers; + jsDocParsingMode?: JSDocParsingMode; } export interface TranspileOutput { @@ -121,7 +122,7 @@ export function transpileModule(input: string, transpileOptions: TranspileOption languageVersion: getEmitScriptTarget(options), impliedNodeFormat: getImpliedNodeFormatForFile(toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*packageJsonInfoCache*/ undefined, compilerHost, options), setExternalModuleIndicator: getSetExternalModuleIndicator(options), - jsDocParsingMode: JSDocParsingMode.ParseNone, + jsDocParsingMode: transpileOptions.jsDocParsingMode ?? JSDocParsingMode.ParseNone, }, ); if (transpileOptions.moduleName) { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b051e45f608..a55b003f6c8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -11618,6 +11618,7 @@ declare namespace ts { moduleName?: string; renamedDependencies?: MapLike; transformers?: CustomTransformers; + jsDocParsingMode?: JSDocParsingMode; } interface TranspileOutput { outputText: string; From 8da01f3583e4a13fcc7088f58dce6ee0c4f5df3e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Dec 2023 10:38:04 -0800 Subject: [PATCH 08/12] Check callback parameters bivariantly if they result from instantiation (#56218) --- src/compiler/checker.ts | 9 +- .../reference/covariantCallbacks.errors.txt | 59 +++++++- .../baselines/reference/covariantCallbacks.js | 47 ++++++ .../reference/covariantCallbacks.symbols | 138 ++++++++++++++++++ .../reference/covariantCallbacks.types | 123 ++++++++++++++++ ...lWithGenericSignatureArguments3.errors.txt | 6 +- .../covariantCallbacks.ts | 37 +++++ 7 files changed, 414 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 289a98a4295..91ef12d2a29 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20691,8 +20691,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); + const sourceSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(source, i) ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); + const targetSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(target, i) ? undefined : getSingleCallSignature(getNonNullableType(targetType)); const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && getTypeFacts(sourceType, TypeFacts.IsUndefinedOrNull) === getTypeFacts(targetType, TypeFacts.IsUndefinedOrNull); let related = callbacks ? @@ -33486,6 +33486,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } + function isInstantiatedGenericParameter(signature: Signature, pos: number) { + let type; + return !!(signature.target && (type = tryGetTypeAtPosition(signature.target, pos)) && isGenericType(type)); + } + // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. function getSingleCallSignature(type: Type): Signature | undefined { return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false); diff --git a/tests/baselines/reference/covariantCallbacks.errors.txt b/tests/baselines/reference/covariantCallbacks.errors.txt index 5de161c1ab5..7a9e34234fc 100644 --- a/tests/baselines/reference/covariantCallbacks.errors.txt +++ b/tests/baselines/reference/covariantCallbacks.errors.txt @@ -23,9 +23,18 @@ covariantCallbacks.ts(69,5): error TS2322: Type 'AList4' is not assignable to ty Types of parameters 'cb' and 'cb' are incompatible. Types of parameters 'item' and 'item' are incompatible. Type 'A' is not assignable to type 'B'. +covariantCallbacks.ts(98,1): error TS2322: Type 'SetLike1<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. + Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'unknown' is not assignable to type 'string'. +covariantCallbacks.ts(106,1): error TS2322: Type 'SetLike2<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. + The types returned by 'get()' are incompatible between these types. + Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'unknown' is not assignable to type 'string'. -==== covariantCallbacks.ts (6 errors) ==== +==== covariantCallbacks.ts (8 errors) ==== // Test that callback parameters are related covariantly interface P { @@ -128,4 +137,52 @@ covariantCallbacks.ts(69,5): error TS2322: Type 'AList4' is not assignable to ty !!! error TS2322: Types of parameters 'item' and 'item' are incompatible. !!! error TS2322: Type 'A' is not assignable to type 'B'. } + + // Repro from #51620 + + type Bivar = { set(value: T): void } + + declare let bu: Bivar; + declare let bs: Bivar; + bu = bs; + bs = bu; + + declare let bfu: Bivar<(x: unknown) => void>; + declare let bfs: Bivar<(x: string) => void>; + bfu = bfs; + bfs = bfu; + + type Bivar1 = { set(value: T): void } + type Bivar2 = { set(value: T): void } + + declare let b1fu: Bivar1<(x: unknown) => void>; + declare let b2fs: Bivar2<(x: string) => void>; + b1fu = b2fs; + b2fs = b1fu; + + type SetLike = { set(value: T): void, get(): T } + + declare let sx: SetLike1<(x: unknown) => void>; + declare let sy: SetLike1<(x: string) => void>; + sx = sy; // Error + ~~ +!!! error TS2322: Type 'SetLike1<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. +!!! error TS2322: Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + sy = sx; + + type SetLike1 = { set(value: T): void, get(): T } + type SetLike2 = { set(value: T): void, get(): T } + + declare let s1: SetLike1<(x: unknown) => void>; + declare let s2: SetLike2<(x: string) => void>; + s1 = s2; // Error + ~~ +!!! error TS2322: Type 'SetLike2<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. +!!! error TS2322: The types returned by 'get()' are incompatible between these types. +!!! error TS2322: Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + s2 = s1; \ No newline at end of file diff --git a/tests/baselines/reference/covariantCallbacks.js b/tests/baselines/reference/covariantCallbacks.js index 38578f1af5c..226e7d3ab55 100644 --- a/tests/baselines/reference/covariantCallbacks.js +++ b/tests/baselines/reference/covariantCallbacks.js @@ -71,6 +71,43 @@ function f14(a: AList4, b: BList4) { a = b; b = a; // Error } + +// Repro from #51620 + +type Bivar = { set(value: T): void } + +declare let bu: Bivar; +declare let bs: Bivar; +bu = bs; +bs = bu; + +declare let bfu: Bivar<(x: unknown) => void>; +declare let bfs: Bivar<(x: string) => void>; +bfu = bfs; +bfs = bfu; + +type Bivar1 = { set(value: T): void } +type Bivar2 = { set(value: T): void } + +declare let b1fu: Bivar1<(x: unknown) => void>; +declare let b2fs: Bivar2<(x: string) => void>; +b1fu = b2fs; +b2fs = b1fu; + +type SetLike = { set(value: T): void, get(): T } + +declare let sx: SetLike1<(x: unknown) => void>; +declare let sy: SetLike1<(x: string) => void>; +sx = sy; // Error +sy = sx; + +type SetLike1 = { set(value: T): void, get(): T } +type SetLike2 = { set(value: T): void, get(): T } + +declare let s1: SetLike1<(x: unknown) => void>; +declare let s2: SetLike2<(x: string) => void>; +s1 = s2; // Error +s2 = s1; //// [covariantCallbacks.js] @@ -101,3 +138,13 @@ function f14(a, b) { a = b; b = a; // Error } +bu = bs; +bs = bu; +bfu = bfs; +bfs = bfu; +b1fu = b2fs; +b2fs = b1fu; +sx = sy; // Error +sy = sx; +s1 = s2; // Error +s2 = s1; diff --git a/tests/baselines/reference/covariantCallbacks.symbols b/tests/baselines/reference/covariantCallbacks.symbols index c710196e50b..ca168fca246 100644 --- a/tests/baselines/reference/covariantCallbacks.symbols +++ b/tests/baselines/reference/covariantCallbacks.symbols @@ -207,3 +207,141 @@ function f14(a: AList4, b: BList4) { >a : Symbol(a, Decl(covariantCallbacks.ts, 66, 13)) } +// Repro from #51620 + +type Bivar = { set(value: T): void } +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 73, 11)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 73, 17)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 73, 22)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 73, 11)) + +declare let bu: Bivar; +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) + +declare let bs: Bivar; +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) + +bu = bs; +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) + +bs = bu; +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) + +declare let bfu: Bivar<(x: unknown) => void>; +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 80, 24)) + +declare let bfs: Bivar<(x: string) => void>; +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 81, 24)) + +bfu = bfs; +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) + +bfs = bfu; +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) + +type Bivar1 = { set(value: T): void } +>Bivar1 : Symbol(Bivar1, Decl(covariantCallbacks.ts, 83, 10)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 85, 12)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 85, 18)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 85, 23)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 85, 12)) + +type Bivar2 = { set(value: T): void } +>Bivar2 : Symbol(Bivar2, Decl(covariantCallbacks.ts, 85, 40)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 86, 12)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 86, 18)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 86, 23)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 86, 12)) + +declare let b1fu: Bivar1<(x: unknown) => void>; +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) +>Bivar1 : Symbol(Bivar1, Decl(covariantCallbacks.ts, 83, 10)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 88, 26)) + +declare let b2fs: Bivar2<(x: string) => void>; +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) +>Bivar2 : Symbol(Bivar2, Decl(covariantCallbacks.ts, 85, 40)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 89, 26)) + +b1fu = b2fs; +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) + +b2fs = b1fu; +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) + +type SetLike = { set(value: T): void, get(): T } +>SetLike : Symbol(SetLike, Decl(covariantCallbacks.ts, 91, 12)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 93, 19)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 93, 24)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 93, 40)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) + +declare let sx: SetLike1<(x: unknown) => void>; +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 95, 26)) + +declare let sy: SetLike1<(x: string) => void>; +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 96, 26)) + +sx = sy; // Error +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) + +sy = sx; +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) + +type SetLike1 = { set(value: T): void, get(): T } +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 100, 20)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 100, 25)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 100, 41)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) + +type SetLike2 = { set(value: T): void, get(): T } +>SetLike2 : Symbol(SetLike2, Decl(covariantCallbacks.ts, 100, 52)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 101, 20)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 101, 25)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 101, 41)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) + +declare let s1: SetLike1<(x: unknown) => void>; +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 103, 26)) + +declare let s2: SetLike2<(x: string) => void>; +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) +>SetLike2 : Symbol(SetLike2, Decl(covariantCallbacks.ts, 100, 52)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 104, 26)) + +s1 = s2; // Error +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) + +s2 = s1; +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) + diff --git a/tests/baselines/reference/covariantCallbacks.types b/tests/baselines/reference/covariantCallbacks.types index 1b2f082da52..849ff661417 100644 --- a/tests/baselines/reference/covariantCallbacks.types +++ b/tests/baselines/reference/covariantCallbacks.types @@ -170,3 +170,126 @@ function f14(a: AList4, b: BList4) { >a : AList4 } +// Repro from #51620 + +type Bivar = { set(value: T): void } +>Bivar : Bivar +>set : (value: T) => void +>value : T + +declare let bu: Bivar; +>bu : Bivar + +declare let bs: Bivar; +>bs : Bivar + +bu = bs; +>bu = bs : Bivar +>bu : Bivar +>bs : Bivar + +bs = bu; +>bs = bu : Bivar +>bs : Bivar +>bu : Bivar + +declare let bfu: Bivar<(x: unknown) => void>; +>bfu : Bivar<(x: unknown) => void> +>x : unknown + +declare let bfs: Bivar<(x: string) => void>; +>bfs : Bivar<(x: string) => void> +>x : string + +bfu = bfs; +>bfu = bfs : Bivar<(x: string) => void> +>bfu : Bivar<(x: unknown) => void> +>bfs : Bivar<(x: string) => void> + +bfs = bfu; +>bfs = bfu : Bivar<(x: unknown) => void> +>bfs : Bivar<(x: string) => void> +>bfu : Bivar<(x: unknown) => void> + +type Bivar1 = { set(value: T): void } +>Bivar1 : Bivar1 +>set : (value: T) => void +>value : T + +type Bivar2 = { set(value: T): void } +>Bivar2 : Bivar2 +>set : (value: T) => void +>value : T + +declare let b1fu: Bivar1<(x: unknown) => void>; +>b1fu : Bivar1<(x: unknown) => void> +>x : unknown + +declare let b2fs: Bivar2<(x: string) => void>; +>b2fs : Bivar2<(x: string) => void> +>x : string + +b1fu = b2fs; +>b1fu = b2fs : Bivar2<(x: string) => void> +>b1fu : Bivar1<(x: unknown) => void> +>b2fs : Bivar2<(x: string) => void> + +b2fs = b1fu; +>b2fs = b1fu : Bivar1<(x: unknown) => void> +>b2fs : Bivar2<(x: string) => void> +>b1fu : Bivar1<(x: unknown) => void> + +type SetLike = { set(value: T): void, get(): T } +>SetLike : SetLike +>set : (value: T) => void +>value : T +>get : () => T + +declare let sx: SetLike1<(x: unknown) => void>; +>sx : SetLike1<(x: unknown) => void> +>x : unknown + +declare let sy: SetLike1<(x: string) => void>; +>sy : SetLike1<(x: string) => void> +>x : string + +sx = sy; // Error +>sx = sy : SetLike1<(x: string) => void> +>sx : SetLike1<(x: unknown) => void> +>sy : SetLike1<(x: string) => void> + +sy = sx; +>sy = sx : SetLike1<(x: unknown) => void> +>sy : SetLike1<(x: string) => void> +>sx : SetLike1<(x: unknown) => void> + +type SetLike1 = { set(value: T): void, get(): T } +>SetLike1 : SetLike1 +>set : (value: T) => void +>value : T +>get : () => T + +type SetLike2 = { set(value: T): void, get(): T } +>SetLike2 : SetLike2 +>set : (value: T) => void +>value : T +>get : () => T + +declare let s1: SetLike1<(x: unknown) => void>; +>s1 : SetLike1<(x: unknown) => void> +>x : unknown + +declare let s2: SetLike2<(x: string) => void>; +>s2 : SetLike2<(x: string) => void> +>x : string + +s1 = s2; // Error +>s1 = s2 : SetLike2<(x: string) => void> +>s1 : SetLike1<(x: unknown) => void> +>s2 : SetLike2<(x: string) => void> + +s2 = s1; +>s2 = s1 : SetLike1<(x: unknown) => void> +>s2 : SetLike2<(x: string) => void> +>s1 : SetLike1<(x: unknown) => void> + diff --git a/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt b/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt index 6e9abea9199..5fd2927b274 100644 --- a/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt +++ b/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt @@ -1,6 +1,7 @@ genericCallWithGenericSignatureArguments3.ts(32,19): error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'. Types of parameters 'a1' and 'x' are incompatible. - Type 'boolean' is not assignable to type 'string'. + Type '(a: string) => boolean' is not assignable to type '(y: string) => string'. + Type 'boolean' is not assignable to type 'string'. genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'. Type 'number' is not assignable to type '(n: Object) => 1'. @@ -41,7 +42,8 @@ genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of t ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'. !!! error TS2345: Types of parameters 'a1' and 'x' are incompatible. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. +!!! error TS2345: Type '(a: string) => boolean' is not assignable to type '(y: string) => string'. +!!! error TS2345: Type 'boolean' is not assignable to type 'string'. var r12 = foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'. diff --git a/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts index 4f3e7ecda0d..4f747be593f 100644 --- a/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts +++ b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts @@ -71,3 +71,40 @@ function f14(a: AList4, b: BList4) { a = b; b = a; // Error } + +// Repro from #51620 + +type Bivar = { set(value: T): void } + +declare let bu: Bivar; +declare let bs: Bivar; +bu = bs; +bs = bu; + +declare let bfu: Bivar<(x: unknown) => void>; +declare let bfs: Bivar<(x: string) => void>; +bfu = bfs; +bfs = bfu; + +type Bivar1 = { set(value: T): void } +type Bivar2 = { set(value: T): void } + +declare let b1fu: Bivar1<(x: unknown) => void>; +declare let b2fs: Bivar2<(x: string) => void>; +b1fu = b2fs; +b2fs = b1fu; + +type SetLike = { set(value: T): void, get(): T } + +declare let sx: SetLike1<(x: unknown) => void>; +declare let sy: SetLike1<(x: string) => void>; +sx = sy; // Error +sy = sx; + +type SetLike1 = { set(value: T): void, get(): T } +type SetLike2 = { set(value: T): void, get(): T } + +declare let s1: SetLike1<(x: unknown) => void>; +declare let s2: SetLike2<(x: string) => void>; +s1 = s2; // Error +s2 = s1; From 99d243579de597d121a8d768c4bd5a95f61f6e82 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 2 Dec 2023 01:26:22 +0200 Subject: [PATCH 09/12] fix(42220): Missing 'used before declaration' for class expression used in own computed property name (#56514) --- src/compiler/checker.ts | 2 +- ...PropertyNamesWithStaticProperty.errors.txt | 60 ++++++++++----- ...computedPropertyNamesWithStaticProperty.js | 44 ++++++++--- ...tedPropertyNamesWithStaticProperty.symbols | 74 ++++++++++++++----- ...putedPropertyNamesWithStaticProperty.types | 66 +++++++++++++---- ...computedPropertyNamesWithStaticProperty.ts | 21 ++++-- 6 files changed, 199 insertions(+), 68 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 91ef12d2a29..d1de194a79c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2837,7 +2837,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a) return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration as VariableDeclaration, usage); } - else if (isClassDeclaration(declaration)) { + else if (isClassLike(declaration)) { // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} }) return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration); } diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt index ad9d57b5401..466c6664966 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt @@ -1,25 +1,49 @@ -computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C' used before its declaration. -computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C' used before its declaration. -computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C1' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C1' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C1' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(14,10): error TS2449: Class 'C2' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(17,10): error TS2449: Class 'C2' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used before its declaration. -==== computedPropertyNamesWithStaticProperty.ts (3 errors) ==== - class C { +==== computedPropertyNamesWithStaticProperty.ts (6 errors) ==== + class C1 { static staticProp = 10; - get [C.staticProp]() { - ~ -!!! error TS2449: Class 'C' used before its declaration. -!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here. + get [C1.staticProp]() { + ~~ +!!! error TS2449: Class 'C1' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here. return "hello"; } - set [C.staticProp](x: string) { - ~ -!!! error TS2449: Class 'C' used before its declaration. -!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here. + set [C1.staticProp](x: string) { + ~~ +!!! error TS2449: Class 'C1' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here. var y = x; } - [C.staticProp]() { } - ~ -!!! error TS2449: Class 'C' used before its declaration. -!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here. - } \ No newline at end of file + [C1.staticProp]() { } + ~~ +!!! error TS2449: Class 'C1' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here. + } + + (class C2 { + static staticProp = 10; + get [C2.staticProp]() { + ~~ +!!! error TS2449: Class 'C2' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here. + return "hello"; + } + set [C2.staticProp](x: string) { + ~~ +!!! error TS2449: Class 'C2' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here. + var y = x; + } + [C2.staticProp]() { } + ~~ +!!! error TS2449: Class 'C2' used before its declaration. +!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here. + }) + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js index aaface52b35..63068159d90 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.js @@ -1,25 +1,49 @@ //// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] //// //// [computedPropertyNamesWithStaticProperty.ts] -class C { +class C1 { static staticProp = 10; - get [C.staticProp]() { + get [C1.staticProp]() { return "hello"; } - set [C.staticProp](x: string) { + set [C1.staticProp](x: string) { var y = x; } - [C.staticProp]() { } -} + [C1.staticProp]() { } +} + +(class C2 { + static staticProp = 10; + get [C2.staticProp]() { + return "hello"; + } + set [C2.staticProp](x: string) { + var y = x; + } + [C2.staticProp]() { } +}) + //// [computedPropertyNamesWithStaticProperty.js] -class C { - get [C.staticProp]() { +var _a; +class C1 { + get [C1.staticProp]() { return "hello"; } - set [C.staticProp](x) { + set [C1.staticProp](x) { var y = x; } - [C.staticProp]() { } + [C1.staticProp]() { } } -C.staticProp = 10; +C1.staticProp = 10; +(_a = class C2 { + get [C2.staticProp]() { + return "hello"; + } + set [C2.staticProp](x) { + var y = x; + } + [C2.staticProp]() { } + }, + _a.staticProp = 10, + _a); diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.symbols b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.symbols index 3b6b3d1aeb0..42410e531eb 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.symbols +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.symbols @@ -1,34 +1,68 @@ //// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] //// === computedPropertyNamesWithStaticProperty.ts === -class C { ->C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) +class C1 { +>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) static staticProp = 10; ->staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) +>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) - get [C.staticProp]() { ->[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 1, 27)) ->C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) ->C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) ->staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) + get [C1.staticProp]() { +>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 1, 27)) +>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) +>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) +>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) return "hello"; } - set [C.staticProp](x: string) { ->[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 4, 5)) ->C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) ->C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) ->staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) ->x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 23)) + set [C1.staticProp](x: string) { +>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 4, 5)) +>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) +>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) +>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) +>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 24)) var y = x; >y : Symbol(y, Decl(computedPropertyNamesWithStaticProperty.ts, 6, 11)) ->x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 23)) +>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 24)) } - [C.staticProp]() { } ->[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 7, 5)) ->C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) ->C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) ->staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9)) + [C1.staticProp]() { } +>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 7, 5)) +>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) +>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0)) +>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10)) } + +(class C2 { +>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1)) + + static staticProp = 10; +>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) + + get [C2.staticProp]() { +>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 12, 27)) +>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) +>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1)) +>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) + + return "hello"; + } + set [C2.staticProp](x: string) { +>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 15, 5)) +>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) +>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1)) +>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) +>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 16, 24)) + + var y = x; +>y : Symbol(y, Decl(computedPropertyNamesWithStaticProperty.ts, 17, 11)) +>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 16, 24)) + } + [C2.staticProp]() { } +>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 18, 5)) +>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) +>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1)) +>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11)) + +}) + diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.types b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.types index f4707536a6a..00d4cdf9e21 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.types +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.types @@ -1,26 +1,26 @@ //// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] //// === computedPropertyNamesWithStaticProperty.ts === -class C { ->C : C +class C1 { +>C1 : C1 static staticProp = 10; >staticProp : number >10 : 10 - get [C.staticProp]() { ->[C.staticProp] : string ->C.staticProp : number ->C : typeof C + get [C1.staticProp]() { +>[C1.staticProp] : string +>C1.staticProp : number +>C1 : typeof C1 >staticProp : number return "hello"; >"hello" : "hello" } - set [C.staticProp](x: string) { ->[C.staticProp] : string ->C.staticProp : number ->C : typeof C + set [C1.staticProp](x: string) { +>[C1.staticProp] : string +>C1.staticProp : number +>C1 : typeof C1 >staticProp : number >x : string @@ -28,9 +28,47 @@ class C { >y : string >x : string } - [C.staticProp]() { } ->[C.staticProp] : () => void ->C.staticProp : number ->C : typeof C + [C1.staticProp]() { } +>[C1.staticProp] : () => void +>C1.staticProp : number +>C1 : typeof C1 >staticProp : number } + +(class C2 { +>(class C2 { static staticProp = 10; get [C2.staticProp]() { return "hello"; } set [C2.staticProp](x: string) { var y = x; } [C2.staticProp]() { }}) : typeof C2 +>class C2 { static staticProp = 10; get [C2.staticProp]() { return "hello"; } set [C2.staticProp](x: string) { var y = x; } [C2.staticProp]() { }} : typeof C2 +>C2 : typeof C2 + + static staticProp = 10; +>staticProp : number +>10 : 10 + + get [C2.staticProp]() { +>[C2.staticProp] : string +>C2.staticProp : number +>C2 : typeof C2 +>staticProp : number + + return "hello"; +>"hello" : "hello" + } + set [C2.staticProp](x: string) { +>[C2.staticProp] : string +>C2.staticProp : number +>C2 : typeof C2 +>staticProp : number +>x : string + + var y = x; +>y : string +>x : string + } + [C2.staticProp]() { } +>[C2.staticProp] : () => void +>C2.staticProp : number +>C2 : typeof C2 +>staticProp : number + +}) + diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts index 4cd9047581f..2d6f92b9bde 100644 --- a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts @@ -1,11 +1,22 @@ // @target: es6 -class C { +class C1 { static staticProp = 10; - get [C.staticProp]() { + get [C1.staticProp]() { return "hello"; } - set [C.staticProp](x: string) { + set [C1.staticProp](x: string) { var y = x; } - [C.staticProp]() { } -} \ No newline at end of file + [C1.staticProp]() { } +} + +(class C2 { + static staticProp = 10; + get [C2.staticProp]() { + return "hello"; + } + set [C2.staticProp](x: string) { + var y = x; + } + [C2.staticProp]() { } +}) From 3500c92a788bcb9775486814b890686c013a5a8c Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 2 Dec 2023 01:48:36 +0200 Subject: [PATCH 10/12] feat(56600): JSDoc @callback doesn't support this parameters via @this (#56610) --- src/compiler/checker.ts | 13 ++++++---- src/compiler/parser.ts | 8 +++--- .../baselines/reference/callbackTag4.symbols | 23 +++++++++++++++++ tests/baselines/reference/callbackTag4.types | 25 +++++++++++++++++++ tests/cases/conformance/jsdoc/callbackTag4.ts | 19 ++++++++++++++ 5 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/callbackTag4.symbols create mode 100644 tests/baselines/reference/callbackTag4.types create mode 100644 tests/cases/conformance/jsdoc/callbackTag4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1de194a79c..9ee8fe65728 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -597,6 +597,7 @@ import { isJSDocSatisfiesTag, isJSDocSignature, isJSDocTemplateTag, + isJSDocThisTag, isJSDocTypeAlias, isJSDocTypeAssertion, isJSDocTypedefTag, @@ -15079,6 +15080,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let flags = SignatureFlags.None; let minArgumentCount = 0; let thisParameter: Symbol | undefined; + let thisTag: JSDocThisTag | undefined = isInJSFile(declaration) ? getJSDocThisTag(declaration) : undefined; let hasThisParameter = false; const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); @@ -15096,6 +15098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // signature. for (let i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) { const param = declaration.parameters[i]; + if (isInJSFile(param) && isJSDocThisTag(param)) { + thisTag = param; + continue; + } let paramSymbol = param.symbol; const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; @@ -15139,11 +15145,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - if (isInJSFile(declaration)) { - const thisTag = getJSDocThisTag(declaration); - if (thisTag && thisTag.typeExpression) { - thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression)); - } + if (thisTag && thisTag.typeExpression) { + thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression)); } const hostDeclaration = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index fcf95696eb9..9da128e705a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -9343,7 +9343,7 @@ namespace Parser { function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const pos = getNodePos(); - let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | false; + let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | JSDocThisTag | false; let children: JSDocPropertyLikeTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { @@ -9635,7 +9635,7 @@ namespace Parser { return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false; } - function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { + function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false { let canParseTag = true; let seenAsterisk = false; while (true) { @@ -9672,7 +9672,7 @@ namespace Parser { } } - function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { + function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false { Debug.assert(token() === SyntaxKind.AtToken); const start = scanner.getTokenFullStart(); nextTokenJSDoc(); @@ -9694,6 +9694,8 @@ namespace Parser { break; case "template": return parseTemplateTag(start, tagName, indent, indentText); + case "this": + return parseThisTag(start, tagName, indent, indentText); default: return false; } diff --git a/tests/baselines/reference/callbackTag4.symbols b/tests/baselines/reference/callbackTag4.symbols new file mode 100644 index 00000000000..17c0d29004c --- /dev/null +++ b/tests/baselines/reference/callbackTag4.symbols @@ -0,0 +1,23 @@ +//// [tests/cases/conformance/jsdoc/callbackTag4.ts] //// + +=== ./a.js === +/** + * @callback C + * @this {{ a: string, b: number }} + * @param {string} a + * @param {number} b + * @returns {boolean} + */ + +/** @type {C} */ +const cb = function (a, b) { +>cb : Symbol(cb, Decl(a.js, 9, 5)) +>a : Symbol(a, Decl(a.js, 9, 21)) +>b : Symbol(b, Decl(a.js, 9, 23)) + + this +>this : Symbol(this) + + return true +} + diff --git a/tests/baselines/reference/callbackTag4.types b/tests/baselines/reference/callbackTag4.types new file mode 100644 index 00000000000..1afbc752a07 --- /dev/null +++ b/tests/baselines/reference/callbackTag4.types @@ -0,0 +1,25 @@ +//// [tests/cases/conformance/jsdoc/callbackTag4.ts] //// + +=== ./a.js === +/** + * @callback C + * @this {{ a: string, b: number }} + * @param {string} a + * @param {number} b + * @returns {boolean} + */ + +/** @type {C} */ +const cb = function (a, b) { +>cb : C +>function (a, b) { this return true} : (this: { a: string; b: number; }, a: string, b: number) => boolean +>a : string +>b : number + + this +>this : { a: string; b: number; } + + return true +>true : true +} + diff --git a/tests/cases/conformance/jsdoc/callbackTag4.ts b/tests/cases/conformance/jsdoc/callbackTag4.ts new file mode 100644 index 00000000000..a5ac356aedd --- /dev/null +++ b/tests/cases/conformance/jsdoc/callbackTag4.ts @@ -0,0 +1,19 @@ +// @allowJs: true +// @checkJs: true +// @strict: true +// @noEmit: true +// @filename: ./a.js + +/** + * @callback C + * @this {{ a: string, b: number }} + * @param {string} a + * @param {number} b + * @returns {boolean} + */ + +/** @type {C} */ +const cb = function (a, b) { + this + return true +} From 8a6ad459d548bb05dc80e18c336ca31e8901e7fd Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 1 Dec 2023 17:17:02 -0800 Subject: [PATCH 11/12] ParseNone -> ParseAll (#56639) --- src/services/transpile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 0b708e62826..a15b48d8d74 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -122,7 +122,7 @@ export function transpileModule(input: string, transpileOptions: TranspileOption languageVersion: getEmitScriptTarget(options), impliedNodeFormat: getImpliedNodeFormatForFile(toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*packageJsonInfoCache*/ undefined, compilerHost, options), setExternalModuleIndicator: getSetExternalModuleIndicator(options), - jsDocParsingMode: transpileOptions.jsDocParsingMode ?? JSDocParsingMode.ParseNone, + jsDocParsingMode: transpileOptions.jsDocParsingMode ?? JSDocParsingMode.ParseAll, }, ); if (transpileOptions.moduleName) { From 670815f768afb613ff2651b16dc4258aeb33a036 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Sat, 2 Dec 2023 06:14:47 +0000 Subject: [PATCH 12/12] Update package-lock.json --- package-lock.json | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a1d304bceb..c45b0309631 100644 --- a/package-lock.json +++ b/package-lock.json @@ -568,9 +568,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -591,9 +591,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -951,9 +951,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz", - "integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==", + "version": "20.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.2.tgz", + "integrity": "sha512-37MXfxkb0vuIlRKHNxwCkb60PNBpR94u4efQuN4JgIAm66zfCDXGSAFCef9XUWFovX2R1ok6Z7MHhtdVXXkkIw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1839,15 +1839,15 @@ } }, "node_modules/eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -4258,9 +4258,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -4275,9 +4275,9 @@ } }, "@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true }, "@humanwhocodes/config-array": { @@ -4565,9 +4565,9 @@ "dev": true }, "@types/node": { - "version": "20.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz", - "integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==", + "version": "20.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.2.tgz", + "integrity": "sha512-37MXfxkb0vuIlRKHNxwCkb60PNBpR94u4efQuN4JgIAm66zfCDXGSAFCef9XUWFovX2R1ok6Z7MHhtdVXXkkIw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -5206,15 +5206,15 @@ "dev": true }, "eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8",