diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 781bf2217d847..c1e4f0abb5533 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, @@ -13731,7 +13737,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); @@ -13913,9 +13919,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 { @@ -17612,7 +17621,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)); } @@ -18194,7 +18203,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)); } } @@ -40020,7 +40029,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 5f59683d955ca..2a8538e68608e 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 be8cfd614315f..9f401c2f1ce91 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 6028775c7b366..ebb570f319ea8 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.symbols +++ b/tests/baselines/reference/mappedTypeAsClauses.symbols @@ -105,392 +105,389 @@ 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)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeAsClauses.ts, 135, 23)) - -type TS1 = keyof { [P in keyof T as Extract]: string }; ->TS1 : Symbol(TS1, Decl(mappedTypeAsClauses.ts, 135, 74)) +>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)) ->Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) >P : Symbol(P, Decl(mappedTypeAsClauses.ts, 136, 23)) -type TS2 = keyof { [P in keyof T as P & ('a' | 'b' | 'c')]: string }; ->TS2 : Symbol(TS2, Decl(mappedTypeAsClauses.ts, 136, 78)) +type TS1 = keyof { [P in keyof T as Extract]: string }; +>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, 137, 23)) -type TS3 = keyof { [P in keyof T as Exclude]: string }; ->TS3 : Symbol(TS3, Decl(mappedTypeAsClauses.ts, 137, 72)) +type TS2 = keyof { [P in keyof T as P & ('a' | 'b' | 'c')]: string }; +>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)) ->Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >P : Symbol(P, Decl(mappedTypeAsClauses.ts, 138, 23)) -type TS4 = keyof { [P in keyof T as NameMap[P & keyof NameMap]]: string }; ->TS4 : Symbol(TS4, Decl(mappedTypeAsClauses.ts, 138, 78)) +type TS3 = keyof { [P in keyof T as Exclude]: string }; +>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)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) >P : Symbol(P, Decl(mappedTypeAsClauses.ts, 139, 23)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) -type TS5 = keyof { [P in keyof T & keyof NameMap as NameMap[P]]: string }; ->TS5 : Symbol(TS5, Decl(mappedTypeAsClauses.ts, 139, 77)) +type TS4 = keyof { [P in keyof T as NameMap[P & keyof NameMap]]: string }; +>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, 129, 7)) ->NameMap : Symbol(NameMap, Decl(mappedTypeAsClauses.ts, 129, 7)) +>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 TS6 = keyof { [ K in keyof T as V & (K extends U ? K : never)]: string }; ->TS6 : Symbol(TS6, Decl(mappedTypeAsClauses.ts, 140, 77)) +type TS5 = keyof { [P in keyof T & keyof NameMap as NameMap[P]]: string }; +>TS5 : Symbol(TS5, 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)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 141, 23)) >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)) +>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, 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)) - -type TN1 = keyof { [P in keyof T as number extends T[P] ? P : never]: string }; ->TN1 : Symbol(TN1, Decl(mappedTypeAsClauses.ts, 145, 82)) +>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)) @@ -498,47 +495,117 @@ type TN1 = keyof { [P in keyof T as number extends T[P] ? P : never]: string >P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) >P : Symbol(P, Decl(mappedTypeAsClauses.ts, 146, 23)) -type TN2 = keyof { [P in keyof T as 'a' extends P ? 'x' : 'y']: string }; ->TN2 : Symbol(TN2, Decl(mappedTypeAsClauses.ts, 146, 82)) +type TN1 = keyof { [P in keyof T as number extends T[P] ? P : never]: string }; +>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 TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; ->TN3 : Symbol(TN3, Decl(mappedTypeAsClauses.ts, 147, 76)) +type TN2 = keyof { [P in keyof T as 'a' extends P ? 'x' : 'y']: string }; +>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)) ->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)) -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)) +type TN3 = keyof { [P in keyof T as Exclude, 'b'>, 'a'>]: string }; +>TN3 : Symbol(TN3, Decl(mappedTypeAsClauses.ts, 148, 76)) >T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) +>P : Symbol(P, Decl(mappedTypeAsClauses.ts, 149, 23)) >T : Symbol(T, Decl(mappedTypeAsClauses.ts, 149, 9)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) ->K : Symbol(K, Decl(mappedTypeAsClauses.ts, 149, 26)) +>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, 149, 23)) -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)) +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, 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)) ->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)) +>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, 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 f9d426c0e8fec..168e8bd6eaf84 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 ba0222660b860..9256a4541fe05 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"