diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfd479127202c..7ea195d1f2070 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14650,15 +14650,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType) || unknownType, readonlyMask && indexInfo.isReadonly)] : emptyArray; const members = createSymbolTable(); const limitedConstraint = getLimitedConstraint(type); + const nameType = getNameTypeFromMappedType(type.mappedType); + 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, + // In case of a reverse mapped type with an intersection constraint or a name type + // 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) { + if (limitedConstraint || nameType) { const propertyNameType = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique); - if (!isTypeAssignableTo(propertyNameType, limitedConstraint)) { + if (limitedConstraint && !isTypeAssignableTo(propertyNameType, limitedConstraint)) { continue; } + if (nameType) { + const nameMapper = appendTypeMapping(type.mappedType.mapper, getTypeParameterFromMappedType(type.mappedType), propertyNameType); + const instantiatedNameType = instantiateType(nameType, nameMapper); + if (instantiatedNameType.flags & TypeFlags.Never) { + continue; + } + } } const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; @@ -27289,10 +27298,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isGenericMappedType(source) && isGenericMappedType(target)) { inferFromGenericMappedTypes(source, target); } - if (getObjectFlags(target) & ObjectFlags.Mapped && !(target as MappedType).declaration.nameType) { - const constraintType = getConstraintTypeFromMappedType(target as MappedType); - if (inferToMappedType(source, target as MappedType, constraintType)) { - return; + if (getObjectFlags(target) & ObjectFlags.Mapped) { + const mappedType = target as MappedType; + if (getMappedTypeNameTypeKind(mappedType) !== MappedTypeNameTypeKind.Remapping) { + const constraintType = getConstraintTypeFromMappedType(mappedType); + if (inferToMappedType(source, mappedType, constraintType)) { + return; + } } } // Infer from the members of source and target only if the two types are possibly related diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.errors.txt b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.errors.txt new file mode 100644 index 0000000000000..9023a1fd6e2d7 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.errors.txt @@ -0,0 +1,46 @@ +reverseMappedTypeInferFromFilteringNameType1.ts(34,7): error TS2353: Object literal may only specify known properties, and 'doesntExist' does not exist in type 'AllowedNeeds<{ last: boolean; }>'. + + +==== reverseMappedTypeInferFromFilteringNameType1.ts (1 errors) ==== + declare class User { + public name: string; + public last: string; + public age: number; + } + + type AllowedNeeds = { + [K in keyof T as K & keyof User]: T[K]; + }; + + declare function extend( + input: { + [K in keyof T]: { + needs: AllowedNeeds + compute: (x: Pick) => any; + }; + } + ): T + + const inferred1 = extend({ + fullName: { + needs: { + name: true, + last: true, + }, + compute: (user) => `${user.name} ${user.last}`, + }, + }); + + const inferred2 = extend({ + fullName: { + needs: { + last: true, + doesntExist: true // error + ~~~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'doesntExist' does not exist in type 'AllowedNeeds<{ last: boolean; }>'. +!!! related TS6500 reverseMappedTypeInferFromFilteringNameType1.ts:14:7: The expected type comes from property 'needs' which is declared here on type '{ needs: AllowedNeeds<{ last: boolean; }>; compute: (x: Pick) => any; }' + }, + compute: (user) => {}, + }, + }); + \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.symbols b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.symbols new file mode 100644 index 0000000000000..8f886e4f72990 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.symbols @@ -0,0 +1,115 @@ +//// [tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType1.ts] //// + +=== reverseMappedTypeInferFromFilteringNameType1.ts === +declare class User { +>User : Symbol(User, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 0)) + + public name: string; +>name : Symbol(User.name, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 20)) + + public last: string; +>last : Symbol(User.last, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 1, 22)) + + public age: number; +>age : Symbol(User.age, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 2, 22)) +} + +type AllowedNeeds = { +>AllowedNeeds : Symbol(AllowedNeeds, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 4, 1)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 6, 18)) + + [K in keyof T as K & keyof User]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 7, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 6, 18)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 7, 3)) +>User : Symbol(User, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 6, 18)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 7, 3)) + +}; + +declare function extend( +>extend : Symbol(extend, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 8, 2)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 24)) + + input: { +>input : Symbol(input, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 27)) + + [K in keyof T]: { +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 12, 5)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 24)) + + needs: AllowedNeeds +>needs : Symbol(needs, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 12, 21)) +>AllowedNeeds : Symbol(AllowedNeeds, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 4, 1)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 24)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 12, 5)) + + compute: (x: Pick) => any; +>compute : Symbol(compute, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 13, 31)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 14, 16)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>User : Symbol(User, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 24)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 12, 5)) +>User : Symbol(User, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 0)) + + }; + } +): T +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 10, 24)) + +const inferred1 = extend({ +>inferred1 : Symbol(inferred1, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 19, 5)) +>extend : Symbol(extend, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 8, 2)) + + fullName: { +>fullName : Symbol(fullName, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 19, 26)) + + needs: { +>needs : Symbol(needs, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 20, 13)) + + name: true, +>name : Symbol(name, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 21, 12)) + + last: true, +>last : Symbol(last, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 22, 17)) + + }, + compute: (user) => `${user.name} ${user.last}`, +>compute : Symbol(compute, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 24, 6)) +>user : Symbol(user, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 25, 14)) +>user.name : Symbol(name, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 20)) +>user : Symbol(user, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 25, 14)) +>name : Symbol(name, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 0, 20)) +>user.last : Symbol(last, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 1, 22)) +>user : Symbol(user, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 25, 14)) +>last : Symbol(last, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 1, 22)) + + }, +}); + +const inferred2 = extend({ +>inferred2 : Symbol(inferred2, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 29, 5)) +>extend : Symbol(extend, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 8, 2)) + + fullName: { +>fullName : Symbol(fullName, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 29, 26)) + + needs: { +>needs : Symbol(needs, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 30, 13)) + + last: true, +>last : Symbol(last, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 31, 12)) + + doesntExist: true // error +>doesntExist : Symbol(doesntExist, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 32, 17)) + + }, + compute: (user) => {}, +>compute : Symbol(compute, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 34, 6)) +>user : Symbol(user, Decl(reverseMappedTypeInferFromFilteringNameType1.ts, 35, 14)) + + }, +}); + diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.types b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.types new file mode 100644 index 0000000000000..baa6eb96c9fa6 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType1.types @@ -0,0 +1,156 @@ +//// [tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType1.ts] //// + +=== reverseMappedTypeInferFromFilteringNameType1.ts === +declare class User { +>User : User +> : ^^^^ + + public name: string; +>name : string +> : ^^^^^^ + + public last: string; +>last : string +> : ^^^^^^ + + public age: number; +>age : number +> : ^^^^^^ +} + +type AllowedNeeds = { +>AllowedNeeds : AllowedNeeds +> : ^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof User]: T[K]; +}; + +declare function extend( +>extend : (input: { [K in keyof T]: { needs: AllowedNeeds; compute: (x: Pick) => any; }; }) => T +> : ^ ^^ ^^ ^^^^^ + + input: { +>input : { [K in keyof T]: { needs: AllowedNeeds; compute: (x: Pick) => any; }; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^ + + [K in keyof T]: { + needs: AllowedNeeds +>needs : AllowedNeeds +> : ^^^^^^^^^^^^^^^^^^ + + compute: (x: Pick) => any; +>compute : (x: Pick) => any +> : ^ ^^ ^^^^^ +>x : Pick +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + }; + } +): T + +const inferred1 = extend({ +>inferred1 : { fullName: { name: boolean; last: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>extend({ fullName: { needs: { name: true, last: true, }, compute: (user) => `${user.name} ${user.last}`, },}) : { fullName: { name: boolean; last: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>extend : (input: { [K in keyof T]: { needs: AllowedNeeds; compute: (x: Pick) => any; }; }) => T +> : ^ ^^ ^^ ^^^^^ +>{ fullName: { needs: { name: true, last: true, }, compute: (user) => `${user.name} ${user.last}`, },} : { fullName: { needs: { name: true; last: true; }; compute: (user: Pick) => string; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + fullName: { +>fullName : { needs: { name: true; last: true; }; compute: (user: Pick) => string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ needs: { name: true, last: true, }, compute: (user) => `${user.name} ${user.last}`, } : { needs: { name: true; last: true; }; compute: (user: Pick) => string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + needs: { +>needs : { name: true; last: true; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ name: true, last: true, } : { name: true; last: true; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + name: true, +>name : true +> : ^^^^ +>true : true +> : ^^^^ + + last: true, +>last : true +> : ^^^^ +>true : true +> : ^^^^ + + }, + compute: (user) => `${user.name} ${user.last}`, +>compute : (user: Pick) => string +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(user) => `${user.name} ${user.last}` : (user: Pick) => string +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>user : Pick +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>`${user.name} ${user.last}` : string +> : ^^^^^^ +>user.name : string +> : ^^^^^^ +>user : Pick +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>name : string +> : ^^^^^^ +>user.last : string +> : ^^^^^^ +>user : Pick +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>last : string +> : ^^^^^^ + + }, +}); + +const inferred2 = extend({ +>inferred2 : { fullName: { last: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>extend({ fullName: { needs: { last: true, doesntExist: true // error }, compute: (user) => {}, },}) : { fullName: { last: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>extend : (input: { [K in keyof T]: { needs: AllowedNeeds; compute: (x: Pick) => any; }; }) => T +> : ^ ^^ ^^ ^^^^^ +>{ fullName: { needs: { last: true, doesntExist: true // error }, compute: (user) => {}, },} : { fullName: { needs: { last: true; doesntExist: boolean; }; compute: (user: Pick) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + fullName: { +>fullName : { needs: { last: true; doesntExist: boolean; }; compute: (user: Pick) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ needs: { last: true, doesntExist: true // error }, compute: (user) => {}, } : { needs: { last: true; doesntExist: boolean; }; compute: (user: Pick) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + needs: { +>needs : { last: true; doesntExist: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ last: true, doesntExist: true // error } : { last: true; doesntExist: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + last: true, +>last : true +> : ^^^^ +>true : true +> : ^^^^ + + doesntExist: true // error +>doesntExist : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + + }, + compute: (user) => {}, +>compute : (user: Pick) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(user) => {} : (user: Pick) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>user : Pick +> : ^^^^^^^^^^^^^^^^^^ + + }, +}); + diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.errors.txt b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.errors.txt new file mode 100644 index 0000000000000..0cab58fe12be9 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.errors.txt @@ -0,0 +1,196 @@ +reverseMappedTypeInferFromFilteringNameType2.ts(18,7): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +reverseMappedTypeInferFromFilteringNameType2.ts(30,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ entry: "foo"; states: { a: { entry: "foo"; }; }; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(40,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(53,5): error TS2322: Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeInferFromFilteringNameType2.ts(56,64): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(63,5): error TS2322: Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. + Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeInferFromFilteringNameType2.ts(66,68): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(75,26): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(83,26): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(85,36): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; y: "foo"; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(96,68): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ prop: "foo"; nested: { prop: string; }; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(139,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ readonly types: { actors: { src: "str"; logic: () => Promise; }; }; readonly invoke: { readonly src: "str"; }; }'. +reverseMappedTypeInferFromFilteringNameType2.ts(145,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ readonly invoke: { readonly src: "whatever"; }; }'. + + +==== reverseMappedTypeInferFromFilteringNameType2.ts (13 errors) ==== + type StateConfig = { + entry?: TAction; + states?: Record>; + }; + declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string + ? TConfig["entry"] + : string, + >(config: { [K in keyof TConfig as K & 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 reverseMappedTypeInferFromFilteringNameType2.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 as K & 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"; }'. + }); + + interface Stuff { + field: number; + anotherField: string; + } + function doStuffWithStuff(s: { + [K in keyof T as K & keyof Stuff]: T[K]; + }): T { + if (Math.random() > 0.5) { + return s as T; + } else { + return s; + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + const stuff1 = 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 as K & keyof Stuff]: T[K] }[], + ): T[] { + if (Math.random() > 0.5) { + return arr as T[]; + } else { + return arr; + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. +!!! error TS2322: Type '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T as K & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + const stuff2 = 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 as K & keyof XNumber]: T[K]; + }): T; + function bar(props: { x: number; y: string }) { + return foo(props); // no error because lack of excess property check by design + } + const foo1 = foo({ x: 1, y: "foo" }); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + const foo2 = 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 as K & keyof NoErrWithOptProps]: T[K]; + }): T; + const baz1 = baz({ x: 1 }); + const baz2 = baz({ x: 1, z: 123 }); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. + const baz3 = baz({ x: 1, y: "foo" }); + const baz4 = 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 as K & 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; + 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; + }; + } + declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { + types: { actors: ProvidedActor }; + } + ? TConfig["types"]["actors"] + : ProvidedActor, + >(config: { + [K in keyof TConfig as K & keyof MachineConfig]: TConfig[K]; + }): TConfig; + const child = () => Promise.resolve("foo"); + 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 '{ readonly types: { actors: { src: "str"; logic: () => Promise; }; }; readonly 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 '{ readonly invoke: { readonly src: "whatever"; }; }'. + }); + \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.symbols b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.symbols new file mode 100644 index 0000000000000..9cffd133e2b2c --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.symbols @@ -0,0 +1,491 @@ +//// [tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType2.ts] //// + +=== reverseMappedTypeInferFromFilteringNameType2.ts === +type StateConfig = { +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 17)) + + entry?: TAction; +>entry : Symbol(entry, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 44)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 17)) + + states?: Record>; +>states : Symbol(states, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 1, 18)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 17)) + +}; +declare function createMachine< +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 3, 2)) + + TConfig extends StateConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 5, 39)) + + TAction extends string = TConfig["entry"] extends string +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 5, 39)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) + + ? TConfig["entry"] +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) + + : string, +>(config: { [K in keyof TConfig as K & keyof StateConfig]: TConfig[K] }): [ +>config : Symbol(config, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 9, 2)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 9, 13)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 9, 13)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 0, 0)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 9, 13)) + + TAction, +>TAction : Symbol(TAction, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 5, 39)) + + TConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 4, 31)) + +]; +const inferredParams1 = createMachine({ +>inferredParams1 : Symbol(inferredParams1, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 13, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 3, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 13, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 14, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 15, 11)) + + entry: "bar", +>entry : Symbol(entry, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 16, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 19, 4)) + +}); +const inferredParams2 = createMachine({ +>inferredParams2 : Symbol(inferredParams2, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 22, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 3, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 22, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 23, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 24, 11)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 25, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 28, 4)) + +}); + +const checkType = +>checkType : Symbol(checkType, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 32, 5)) + + () => +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 33, 3)) + + (value: { [K in keyof U as K & keyof T]: U[K] }) => +>U : Symbol(U, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 33, 3)) +>value : Symbol(value, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 16)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 26)) +>U : Symbol(U, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 3)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 26)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 33, 3)) +>U : Symbol(U, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 3)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 26)) + + value; +>value : Symbol(value, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 34, 16)) + +const checked = checkType<{ x: number; y: string }>()({ +>checked : Symbol(checked, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 36, 5)) +>checkType : Symbol(checkType, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 32, 5)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 36, 27)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 36, 38)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 36, 55)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 37, 17)) + + z: "z", // undesirable property z is *not* allowed +>z : Symbol(z, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 38, 9)) + +}); + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 40, 3)) + + field: number; +>field : Symbol(Stuff.field, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 42, 17)) + + anotherField: string; +>anotherField : Symbol(Stuff.anotherField, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 43, 16)) +} +function doStuffWithStuff(s: { +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 45, 1)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 26)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 40, 3)) +>s : Symbol(s, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 43)) + + [K in keyof T as K & keyof Stuff]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 47, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 26)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 47, 3)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 40, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 26)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 47, 3)) + +}): T { +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 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, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.float16.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return s as T; +>s : Symbol(s, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 43)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 26)) + + } else { + return s; +>s : Symbol(s, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 46, 43)) + } +} +const stuff1 = doStuffWithStuff({ field: 1, anotherField: "a", extra: 123 }); +>stuff1 : Symbol(stuff1, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 5)) +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 45, 1)) +>field : Symbol(field, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 33)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 43)) +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 62)) + +function doStuffWithStuffArr( +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 77)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 29)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 40, 3)) + + arr: { [K in keyof T as K & keyof Stuff]: T[K] }[], +>arr : Symbol(arr, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 46)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 57, 10)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 29)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 57, 10)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 40, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 29)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 57, 10)) + +): T[] { +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 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, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.float16.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return arr as T[]; +>arr : Symbol(arr, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 46)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 29)) + + } else { + return arr; +>arr : Symbol(arr, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 56, 46)) + } +} +const stuff2 = doStuffWithStuffArr([{ field: 1, anotherField: "a", extra: 123 }]); +>stuff2 : Symbol(stuff2, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 5)) +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 55, 77)) +>field : Symbol(field, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 37)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 47)) +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 66)) + +type XNumber = { x: number }; +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 82)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 67, 16)) + +declare function foo(props: { +>foo : Symbol(foo, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 67, 29)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 68, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 82)) +>props : Symbol(props, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 68, 40)) + + [K in keyof T as K & keyof XNumber]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 69, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 68, 21)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 69, 3)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 65, 82)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 68, 21)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 69, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 68, 21)) + +function bar(props: { x: number; y: string }) { +>bar : Symbol(bar, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 70, 6)) +>props : Symbol(props, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 71, 13)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 71, 21)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 71, 32)) + + return foo(props); // no error because lack of excess property check by design +>foo : Symbol(foo, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 67, 29)) +>props : Symbol(props, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 71, 13)) +} +const foo1 = foo({ x: 1, y: "foo" }); +>foo1 : Symbol(foo1, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 74, 5)) +>foo : Symbol(foo, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 67, 29)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 74, 18)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 74, 24)) + +const foo2 = foo({ ...{ x: 1, y: "foo" } }); // no error because lack of excess property check by design +>foo2 : Symbol(foo2, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 5)) +>foo : Symbol(foo, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 67, 29)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 23)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 29)) + +type NoErrWithOptProps = { x: number; y?: string }; +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 44)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 26)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 37)) + +declare function baz(props: { +>baz : Symbol(baz, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 51)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 78, 21)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 44)) +>props : Symbol(props, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 78, 50)) + + [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 79, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 78, 21)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 79, 3)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 75, 44)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 78, 21)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 79, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 78, 21)) + +const baz1 = baz({ x: 1 }); +>baz1 : Symbol(baz1, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 81, 5)) +>baz : Symbol(baz, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 51)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 81, 18)) + +const baz2 = baz({ x: 1, z: 123 }); +>baz2 : Symbol(baz2, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 82, 5)) +>baz : Symbol(baz, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 51)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 82, 18)) +>z : Symbol(z, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 82, 24)) + +const baz3 = baz({ x: 1, y: "foo" }); +>baz3 : Symbol(baz3, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 83, 5)) +>baz : Symbol(baz, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 51)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 83, 18)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 83, 24)) + +const baz4 = baz({ x: 1, y: "foo", z: 123 }); +>baz4 : Symbol(baz4, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 5)) +>baz : Symbol(baz, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 77, 51)) +>x : Symbol(x, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 18)) +>y : Symbol(y, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 24)) +>z : Symbol(z, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 34)) + +interface WithNestedProp { +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 45)) + + prop: string; +>prop : Symbol(WithNestedProp.prop, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 86, 26)) + + nested: { +>nested : Symbol(WithNestedProp.nested, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 87, 15)) + + prop: string; +>prop : Symbol(prop, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 88, 11)) + + }; +} +declare function withNestedProp(props: { +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 91, 1)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 92, 32)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 45)) +>props : Symbol(props, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 92, 58)) + + [K in keyof T as K & keyof WithNestedProp]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 93, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 92, 32)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 93, 3)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 84, 45)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 92, 32)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 93, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 92, 32)) + +const wnp = withNestedProp({ prop: "foo", nested: { prop: "bar" }, extra: 10 }); +>wnp : Symbol(wnp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 5)) +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 91, 1)) +>prop : Symbol(prop, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 28)) +>nested : Symbol(nested, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 41)) +>prop : Symbol(prop, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 51)) +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 66)) + +type IsLiteralString = string extends T ? false : true; +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 80)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 21)) +>T : Symbol(T, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 21)) + +interface ProvidedActor { +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 73)) + + src: string; +>src : Symbol(ProvidedActor.src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 98, 25)) + + logic: () => Promise; +>logic : Symbol(ProvidedActor.logic, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 99, 14)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +} +type DistributeActors = TActor extends { src: infer TSrc } +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 101, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 102, 22)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 102, 22)) +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 102, 48)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 102, 59)) + + ? { + src: TSrc; +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 103, 5)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 102, 59)) + } + : never; +interface MachineConfig { +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 106, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 107, 24)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 73)) + + types?: { +>types : Symbol(MachineConfig.types, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 107, 55)) + + actors?: TActor; +>actors : Symbol(actors, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 108, 11)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 107, 24)) + + }; + invoke: IsLiteralString extends true +>invoke : Symbol(MachineConfig.invoke, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 110, 4)) +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 95, 80)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 107, 24)) + + ? DistributeActors +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 101, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 107, 24)) + + : { + src: string; +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 113, 7)) + + }; +} +declare function createXMachine< +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 116, 1)) + + const TConfig extends MachineConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 106, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 118, 46)) + + TActor extends ProvidedActor = TConfig extends { +>TActor : Symbol(TActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 118, 46)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 73)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) + + types: { actors: ProvidedActor }; +>types : Symbol(types, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 119, 50)) +>actors : Symbol(actors, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 120, 12)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 73)) + } + ? TConfig["types"]["actors"] +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) + + : ProvidedActor, +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 97, 73)) + +>(config: { +>config : Symbol(config, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 124, 2)) + + [K in keyof TConfig as K & keyof MachineConfig]: TConfig[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 125, 3)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 125, 3)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 106, 10)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) +>K : Symbol(K, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 125, 3)) + +}): TConfig; +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 117, 32)) + +const child = () => Promise.resolve("foo"); +>child : Symbol(child, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 127, 5)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +const config = createXMachine({ +>config : Symbol(config, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 128, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 116, 1)) + + types: {} as { +>types : Symbol(types, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 128, 31)) + + actors: { +>actors : Symbol(actors, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 129, 16)) + + src: "str"; +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 130, 13)) + + logic: typeof child; +>logic : Symbol(logic, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 131, 17)) +>child : Symbol(child, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 127, 5)) + + }; + }, + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 134, 4)) + + src: "str", +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 135, 11)) + + }, + extra: 10, +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 137, 4)) + +}); +const config2 = createXMachine({ +>config2 : Symbol(config2, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 140, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 116, 1)) + + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 140, 32)) + + src: "whatever", +>src : Symbol(src, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 141, 11)) + + }, + extra: 10, +>extra : Symbol(extra, Decl(reverseMappedTypeInferFromFilteringNameType2.ts, 143, 4)) + +}); + diff --git a/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.types b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.types new file mode 100644 index 0000000000000..7bfe37969fd26 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferFromFilteringNameType2.types @@ -0,0 +1,682 @@ +//// [tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType2.ts] //// + +=== Performance Stats === +Instantiation count: 2,500 + +=== reverseMappedTypeInferFromFilteringNameType2.ts === +type StateConfig = { +>StateConfig : StateConfig +> : ^^^^^^^^^^^^^^^^^^^^ + + entry?: TAction; +>entry : TAction | 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 as K & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ + + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string + ? TConfig["entry"] + : string, +>(config: { [K in keyof TConfig as K & keyof StateConfig]: TConfig[K] }): [ +>config : { [K in keyof TConfig as K & keyof StateConfig]: TConfig[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TAction, + TConfig, +]; +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 as K & 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 as K & 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 = +>checkType : () => (value: { [K in keyof U as K & keyof T]: U[K]; }) => { [K in keyof U as K & keyof T]: U[K]; } +> : ^ ^^^^^^^^ ^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + () => +>() => (value: { [K in keyof U as K & keyof T]: U[K] }) => value : () => (value: { [K in keyof U as K & keyof T]: U[K]; }) => { [K in keyof U as K & keyof T]: U[K]; } +> : ^ ^^^^^^^^ ^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + (value: { [K in keyof U as K & keyof T]: U[K] }) => +>(value: { [K in keyof U as K & keyof T]: U[K] }) => value : (value: { [K in keyof U as K & keyof T]: U[K]; }) => { [K in keyof U as K & keyof T]: U[K]; } +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>value : { [K in keyof U as K & keyof T]: U[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + value; +>value : { [K in keyof U as K & 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 as K & ("y" | "x")]: U[K]; }) => { [K in keyof U as K & ("y" | "x")]: U[K]; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>checkType : () => (value: { [K in keyof U as K & keyof T]: U[K]; }) => { [K in keyof U as K & 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" +> : ^^^ + +}); + +interface Stuff { + field: number; +>field : number +> : ^^^^^^ + + anotherField: string; +>anotherField : string +> : ^^^^^^ +} +function doStuffWithStuff(s: { +>doStuffWithStuff : (s: { [K in keyof T as K & keyof Stuff]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>s : { [K in keyof T as K & keyof Stuff]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof Stuff]: T[K]; +}): T { + 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 as K & keyof Stuff]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + } else { + return s; +>s : { [K in keyof T as K & keyof Stuff]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +} +const stuff1 = doStuffWithStuff({ field: 1, anotherField: "a", extra: 123 }); +>stuff1 : { field: 1; anotherField: "a"; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>doStuffWithStuff({ field: 1, anotherField: "a", extra: 123 }) : { field: 1; anotherField: "a"; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>doStuffWithStuff : (s: { [K in keyof T as K & 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( +>doStuffWithStuffArr : (arr: { [K in keyof T as K & keyof Stuff]: T[K]; }[]) => T[] +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + arr: { [K in keyof T as K & keyof Stuff]: T[K] }[], +>arr : { [K in keyof T as K & keyof Stuff]: T[K]; }[] +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +): T[] { + 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 as K & keyof Stuff]: T[K]; }[] +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + } else { + return arr; +>arr : { [K in keyof T as K & keyof Stuff]: T[K]; }[] +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +} +const stuff2 = doStuffWithStuffArr([{ field: 1, anotherField: "a", extra: 123 }]); +>stuff2 : { field: 1; anotherField: "a"; }[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>doStuffWithStuffArr([{ field: 1, anotherField: "a", extra: 123 }]) : { field: 1; anotherField: "a"; }[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>doStuffWithStuffArr : (arr: { [K in keyof T as K & 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: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>field : 1 +> : ^ +>1 : 1 +> : ^ +>anotherField : "a" +> : ^^^ +>"a" : "a" +> : ^^^ +>extra : number +> : ^^^^^^ +>123 : 123 +> : ^^^ + +type XNumber = { x: number }; +>XNumber : XNumber +> : ^^^^^^^ +>x : number +> : ^^^^^^ + +declare function foo(props: { +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>props : { [K in keyof T as K & "x"]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof XNumber]: T[K]; +}): T; +function bar(props: { x: number; y: string }) { +>bar : (props: { x: number; y: string; }) => { x: number; } +> : ^ ^^ ^^^^^^^^^^ ^^^ +>props : { x: number; y: string; } +> : ^^^^^ ^^^^^ ^^^ +>x : number +> : ^^^^^^ +>y : string +> : ^^^^^^ + + return foo(props); // no error because lack of excess property check by design +>foo(props) : { x: number; } +> : ^^^^^ ^^^ +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>props : { x: number; y: string; } +> : ^^^^^ ^^^^^ ^^^ +} +const foo1 = foo({ x: 1, y: "foo" }); +>foo1 : { x: 1; } +> : ^^^^^^^^^ +>foo({ x: 1, y: "foo" }) : { x: 1; } +> : ^^^^^^^^^ +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ x: 1, y: "foo" } : { x: 1; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>x : 1 +> : ^ +>1 : 1 +> : ^ +>y : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +const foo2 = foo({ ...{ x: 1, y: "foo" } }); // no error because lack of excess property check by design +>foo2 : { x: 1; } +> : ^^^^^^^^^ +>foo({ ...{ x: 1, y: "foo" } }) : { x: 1; } +> : ^^^^^^^^^ +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ ...{ 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 : NoErrWithOptProps +> : ^^^^^^^^^^^^^^^^^ +>x : number +> : ^^^^^^ +>y : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + +declare function baz(props: { +>baz : (props: { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>props : { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; +}): T; +const baz1 = baz({ x: 1 }); +>baz1 : { x: 1; } +> : ^^^^^^^^^ +>baz({ x: 1 }) : { x: 1; } +> : ^^^^^^^^^ +>baz : (props: { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ x: 1 } : { x: 1; } +> : ^^^^^^^^^ +>x : 1 +> : ^ +>1 : 1 +> : ^ + +const baz2 = baz({ x: 1, z: 123 }); +>baz2 : { x: 1; } +> : ^^^^^^^^^ +>baz({ x: 1, z: 123 }) : { x: 1; } +> : ^^^^^^^^^ +>baz : (props: { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ x: 1, z: 123 } : { x: 1; z: number; } +> : ^^^^^^^^^^^^^^^^^^^^ +>x : 1 +> : ^ +>1 : 1 +> : ^ +>z : number +> : ^^^^^^ +>123 : 123 +> : ^^^ + +const baz3 = baz({ x: 1, y: "foo" }); +>baz3 : { x: 1; y: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^ +>baz({ x: 1, y: "foo" }) : { x: 1; y: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^ +>baz : (props: { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ x: 1, y: "foo" } : { x: 1; y: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^ +>x : 1 +> : ^ +>1 : 1 +> : ^ +>y : "foo" +> : ^^^^^ +>"foo" : "foo" +> : ^^^^^ + +const baz4 = baz({ x: 1, y: "foo", z: 123 }); +>baz4 : { x: 1; y: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^ +>baz({ x: 1, y: "foo", z: 123 }) : { x: 1; y: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^ +>baz : (props: { [K in keyof T as K & keyof NoErrWithOptProps]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ 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: { +>withNestedProp : (props: { [K in keyof T as K & keyof WithNestedProp]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>props : { [K in keyof T as K & keyof WithNestedProp]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof WithNestedProp]: T[K]; +}): T; +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 as K & 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 +> : ^^^^ + +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 +> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + actors?: TActor; +>actors : TActor | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }; + invoke: IsLiteralString extends true +>invoke : IsLiteralString extends true ? DistributeActors : { src: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>true : true +> : ^^^^ + + ? DistributeActors + : { + src: string; +>src : string +> : ^^^^^^ + + }; +} +declare function createXMachine< +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof TConfig as K & keyof MachineConfig]: TConfig[K]; }) => TConfig +> : ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ + + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { + types: { actors: ProvidedActor }; +>types : { actors: ProvidedActor; } +> : ^^^^^^^^^^ ^^^ +>actors : ProvidedActor +> : ^^^^^^^^^^^^^ + } + ? TConfig["types"]["actors"] + : ProvidedActor, +>(config: { +>config : { [K in keyof TConfig as K & keyof MachineConfig]: TConfig[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof TConfig as K & keyof MachineConfig]: TConfig[K]; +}): TConfig; +const child = () => Promise.resolve("foo"); +>child : () => Promise +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => Promise.resolve("foo") : () => Promise +> : ^^^^^^^^^^^^^^^^^^^^^ +>Promise.resolve("foo") : Promise +> : ^^^^^^^^^^^^^^^ +>Promise.resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ +>Promise : PromiseConstructor +> : ^^^^^^^^^^^^^^^^^^ +>resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ +>"foo" : "foo" +> : ^^^^^ + +const config = createXMachine({ +>config : { readonly types: { actors: { src: "str"; logic: typeof child; }; }; readonly invoke: { readonly src: "str"; }; } +> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>createXMachine({ types: {} as { actors: { src: "str"; logic: typeof child; }; }, invoke: { src: "str", }, extra: 10,}) : { readonly types: { actors: { src: "str"; logic: typeof child; }; }; readonly invoke: { readonly src: "str"; }; } +> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof TConfig as K & keyof MachineConfig]: 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 : () => Promise +> : ^^^^^^^^^^^^^^^^^^^^^ +>child : () => Promise +> : ^^^^^^^^^^^^^^^^^^^^^ + + }; + }, + invoke: { +>invoke : { src: "str"; } +> : ^^^^^^^^^^^^^^^ +>{ src: "str", } : { src: "str"; } +> : ^^^^^^^^^^^^^^^ + + src: "str", +>src : "str" +> : ^^^^^ +>"str" : "str" +> : ^^^^^ + + }, + extra: 10, +>extra : number +> : ^^^^^^ +>10 : 10 +> : ^^ + +}); +const config2 = createXMachine({ +>config2 : { readonly invoke: { readonly src: "whatever"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>createXMachine({ invoke: { src: "whatever", }, extra: 10,}) : { readonly invoke: { readonly src: "whatever"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof TConfig as K & keyof MachineConfig]: 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/reverseMappedTypeLimitedConstraintWithFilteringNameType1.errors.txt b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.errors.txt new file mode 100644 index 0000000000000..257e19303c75a --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.errors.txt @@ -0,0 +1,55 @@ +reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts(5,26): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts(17,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + + +==== reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts (2 errors) ==== + type XNumber = { x: number }; + declare function foo(props: { + [K in keyof T as K & keyof XNumber]: T[K]; + }): T; + const foo1 = foo({ x: 1, y: "foo" }); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + const objFoo = { x: 1, y: "foo" }; + const foo2 = foo(objFoo); + + const checkType = + () => + (value: { [K in keyof U & keyof T]: U[K] }) => + value; + + const checked1 = 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"; }'. + }); + const objChecked = { + x: 1, + y: "y", + z: "z", + }; + const checked2 = checkType<{ x: number; y: string }>()(objChecked); + + declare function fn1>(obj: { + [K in keyof T as K extends "a" ? K : never]: T[K]; + }): T; + const obj1 = { + a: 42, + b: true, + }; + const result1 = fn1(obj1); + + declare function fn2(obj: { + [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; + }): T; + const obj2 = { a: 1, b: 2, c: 3 }; + const result2 = fn2(obj2); + + declare function fn3(obj: { + [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; + }): T; + const obj3 = { a: 1, b: 2, c: 3 }; + const result3 = fn3(obj3); + \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.symbols b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.symbols new file mode 100644 index 0000000000000..de8519fb4e639 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.symbols @@ -0,0 +1,181 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts] //// + +=== reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts === +type XNumber = { x: number }; +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 0)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 16)) + +declare function foo(props: { +>foo : Symbol(foo, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 1, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 0)) +>props : Symbol(props, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 1, 40)) + + [K in keyof T as K & keyof XNumber]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 2, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 1, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 2, 3)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 1, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 2, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 1, 21)) + +const foo1 = foo({ x: 1, y: "foo" }); +>foo1 : Symbol(foo1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 4, 5)) +>foo : Symbol(foo, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 29)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 4, 18)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 4, 24)) + +const objFoo = { x: 1, y: "foo" }; +>objFoo : Symbol(objFoo, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 5, 5)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 5, 16)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 5, 22)) + +const foo2 = foo(objFoo); +>foo2 : Symbol(foo2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 6, 5)) +>foo : Symbol(foo, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 0, 29)) +>objFoo : Symbol(objFoo, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 5, 5)) + +const checkType = +>checkType : Symbol(checkType, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 8, 5)) + + () => +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 9, 3)) + + (value: { [K in keyof U & keyof T]: U[K] }) => +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 9, 3)) +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 16)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 26)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 9, 3)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 3)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 26)) + + value; +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 10, 16)) + +const checked1 = checkType<{ x: number; y: string }>()({ +>checked1 : Symbol(checked1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 13, 5)) +>checkType : Symbol(checkType, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 8, 5)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 13, 28)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 13, 39)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 13, 56)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 14, 17)) + + z: "z", +>z : Symbol(z, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 15, 9)) + +}); +const objChecked = { +>objChecked : Symbol(objChecked, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 18, 5)) + + x: 1, +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 18, 20)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 19, 7)) + + z: "z", +>z : Symbol(z, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 20, 9)) + +}; +const checked2 = checkType<{ x: number; y: string }>()(objChecked); +>checked2 : Symbol(checked2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 23, 5)) +>checkType : Symbol(checkType, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 8, 5)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 23, 28)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 23, 39)) +>objChecked : Symbol(objChecked, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 18, 5)) + +declare function fn1>(obj: { +>fn1 : Symbol(fn1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 23, 67)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 25, 21)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 25, 55)) + + [K in keyof T as K extends "a" ? K : never]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 26, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 25, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 26, 3)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 26, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 25, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 26, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 25, 21)) + +const obj1 = { +>obj1 : Symbol(obj1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 28, 5)) + + a: 42, +>a : Symbol(a, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 28, 14)) + + b: true, +>b : Symbol(b, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 29, 8)) + +}; +const result1 = fn1(obj1); +>result1 : Symbol(result1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 32, 5)) +>fn1 : Symbol(fn1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 23, 67)) +>obj1 : Symbol(obj1, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 28, 5)) + +declare function fn2(obj: { +>fn2 : Symbol(fn2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 32, 26)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 34, 21)) +>obj : Symbol(obj, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 34, 24)) + + [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 35, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 34, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 35, 3)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 35, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 34, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 35, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 34, 21)) + +const obj2 = { a: 1, b: 2, c: 3 }; +>obj2 : Symbol(obj2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 37, 5)) +>a : Symbol(a, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 37, 14)) +>b : Symbol(b, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 37, 20)) +>c : Symbol(c, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 37, 26)) + +const result2 = fn2(obj2); +>result2 : Symbol(result2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 38, 5)) +>fn2 : Symbol(fn2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 32, 26)) +>obj2 : Symbol(obj2, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 37, 5)) + +declare function fn3(obj: { +>fn3 : Symbol(fn3, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 38, 26)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 40, 21)) +>obj : Symbol(obj, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 40, 24)) + + [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 41, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 40, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 41, 3)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 41, 3)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 40, 21)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 41, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 40, 21)) + +const obj3 = { a: 1, b: 2, c: 3 }; +>obj3 : Symbol(obj3, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 43, 5)) +>a : Symbol(a, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 43, 14)) +>b : Symbol(b, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 43, 20)) +>c : Symbol(c, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 43, 26)) + +const result3 = fn3(obj3); +>result3 : Symbol(result3, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 44, 5)) +>fn3 : Symbol(fn3, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 38, 26)) +>obj3 : Symbol(obj3, Decl(reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts, 43, 5)) + diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.types b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.types new file mode 100644 index 0000000000000..dd299c51c8a98 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraintWithFilteringNameType1.types @@ -0,0 +1,264 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts] //// + +=== reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts === +type XNumber = { x: number }; +>XNumber : XNumber +> : ^^^^^^^ +>x : number +> : ^^^^^^ + +declare function foo(props: { +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>props : { [K in keyof T as K & "x"]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K & keyof XNumber]: T[K]; +}): T; +const foo1 = foo({ x: 1, y: "foo" }); +>foo1 : { x: 1; } +> : ^^^^^^^^^ +>foo({ x: 1, y: "foo" }) : { x: 1; } +> : ^^^^^^^^^ +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ x: 1, y: "foo" } : { x: 1; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^ +>x : 1 +> : ^ +>1 : 1 +> : ^ +>y : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +const objFoo = { x: 1, y: "foo" }; +>objFoo : { x: number; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ x: 1, y: "foo" } : { x: number; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ +>y : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +const foo2 = foo(objFoo); +>foo2 : { x: number; } +> : ^^^^^^^^^^^^^^ +>foo(objFoo) : { x: number; } +> : ^^^^^^^^^^^^^^ +>foo : (props: { [K in keyof T as K & keyof XNumber]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>objFoo : { x: number; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + +const checkType = +>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: { [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]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +const checked1 = checkType<{ x: number; y: string }>()({ +>checked1 : { 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" +> : ^^^ + +}); +const objChecked = { +>objChecked : { x: number; y: string; z: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ x: 1, y: "y", z: "z",} : { x: number; y: string; z: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + x: 1, +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ + + y: "y", +>y : string +> : ^^^^^^ +>"y" : "y" +> : ^^^ + + z: "z", +>z : string +> : ^^^^^^ +>"z" : "z" +> : ^^^ + +}; +const checked2 = checkType<{ x: number; y: string }>()(objChecked); +>checked2 : { x: number; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>checkType<{ x: number; y: string }>()(objChecked) : { x: number; y: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>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 +> : ^^^^^^ +>objChecked : { x: number; y: string; z: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare function fn1>(obj: { +>fn1 : >(obj: { [K in keyof T as K extends "a" ? K : never]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>obj : { [K in keyof T as K extends "a" ? K : never]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T as K extends "a" ? K : never]: T[K]; +}): T; +const obj1 = { +>obj1 : { a: number; b: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 42, b: true,} : { a: number; b: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a: 42, +>a : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + b: true, +>b : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +}; +const result1 = fn1(obj1); +>result1 : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn1(obj1) : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn1 : >(obj: { [K in keyof T as K extends "a" ? K : never]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>obj1 : { a: number; b: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare function fn2(obj: { +>fn2 : (obj: { [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; }) => T +> : ^ ^^ ^^ ^^^^^ +>obj : { [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; +}): T; +const obj2 = { a: 1, b: 2, c: 3 }; +>obj2 : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 1, b: 2, c: 3 } : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ +>b : number +> : ^^^^^^ +>2 : 2 +> : ^ +>c : number +> : ^^^^^^ +>3 : 3 +> : ^ + +const result2 = fn2(obj2); +>result2 : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn2(obj2) : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn2 : (obj: { [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; }) => T +> : ^ ^^ ^^ ^^^^^ +>obj2 : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare function fn3(obj: { +>fn3 : (obj: { [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; }) => T +> : ^ ^^ ^^ ^^^^^ +>obj : { [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; +}): T; +const obj3 = { a: 1, b: 2, c: 3 }; +>obj3 : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 1, b: 2, c: 3 } : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ +>b : number +> : ^^^^^^ +>2 : 2 +> : ^ +>c : number +> : ^^^^^^ +>3 : 3 +> : ^ + +const result3 = fn3(obj3); +>result3 : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn3(obj3) : { a: number; } +> : ^^^^^^^^^^^^^^ +>fn3 : (obj: { [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; }) => T +> : ^ ^^ ^^ ^^^^^ +>obj3 : { a: number; b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType1.ts b/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType1.ts new file mode 100644 index 0000000000000..e1d2b8c21b546 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType1.ts @@ -0,0 +1,41 @@ +// @strict: true +// @noEmit: true + +declare class User { + public name: string; + public last: string; + public age: number; +} + +type AllowedNeeds = { + [K in keyof T as K & keyof User]: T[K]; +}; + +declare function extend( + input: { + [K in keyof T]: { + needs: AllowedNeeds + compute: (x: Pick) => any; + }; + } +): T + +const inferred1 = extend({ + fullName: { + needs: { + name: true, + last: true, + }, + compute: (user) => `${user.name} ${user.last}`, + }, +}); + +const inferred2 = extend({ + fullName: { + needs: { + last: true, + doesntExist: true // error + }, + compute: (user) => {}, + }, +}); diff --git a/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType2.ts b/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType2.ts new file mode 100644 index 0000000000000..737050c533a26 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeInferFromFilteringNameType2.ts @@ -0,0 +1,150 @@ +// @strict: true +// @lib: esnext +// @noEmit: true + +type StateConfig = { + entry?: TAction; + states?: Record>; +}; +declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string + ? TConfig["entry"] + : string, +>(config: { [K in keyof TConfig as K & 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 as K & 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 +}); + +interface Stuff { + field: number; + anotherField: string; +} +function doStuffWithStuff(s: { + [K in keyof T as K & keyof Stuff]: T[K]; +}): T { + if (Math.random() > 0.5) { + return s as T; + } else { + return s; + } +} +const stuff1 = doStuffWithStuff({ field: 1, anotherField: "a", extra: 123 }); +function doStuffWithStuffArr( + arr: { [K in keyof T as K & keyof Stuff]: T[K] }[], +): T[] { + if (Math.random() > 0.5) { + return arr as T[]; + } else { + return arr; + } +} +const stuff2 = doStuffWithStuffArr([{ field: 1, anotherField: "a", extra: 123 }]); + +type XNumber = { x: number }; +declare function foo(props: { + [K in keyof T as K & keyof XNumber]: T[K]; +}): T; +function bar(props: { x: number; y: string }) { + return foo(props); // no error because lack of excess property check by design +} +const foo1 = foo({ x: 1, y: "foo" }); +const foo2 = 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 as K & keyof NoErrWithOptProps]: T[K]; +}): T; +const baz1 = baz({ x: 1 }); +const baz2 = baz({ x: 1, z: 123 }); +const baz3 = baz({ x: 1, y: "foo" }); +const baz4 = baz({ x: 1, y: "foo", z: 123 }); + +interface WithNestedProp { + prop: string; + nested: { + prop: string; + }; +} +declare function withNestedProp(props: { + [K in keyof T as K & keyof WithNestedProp]: T[K]; +}): T; +const wnp = withNestedProp({ prop: "foo", nested: { prop: "bar" }, extra: 10 }); + +type IsLiteralString = string extends T ? false : true; +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; + }; +} +declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { + types: { actors: ProvidedActor }; + } + ? TConfig["types"]["actors"] + : ProvidedActor, +>(config: { + [K in keyof TConfig as K & keyof MachineConfig]: 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/reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts b/tests/cases/compiler/reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts new file mode 100644 index 0000000000000..28a3748c0b8c6 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeLimitedConstraintWithFilteringNameType1.ts @@ -0,0 +1,48 @@ +// @strict: true +// @noEmit: true + +type XNumber = { x: number }; +declare function foo(props: { + [K in keyof T as K & keyof XNumber]: T[K]; +}): T; +const foo1 = foo({ x: 1, y: "foo" }); +const objFoo = { x: 1, y: "foo" }; +const foo2 = foo(objFoo); + +const checkType = + () => + (value: { [K in keyof U & keyof T]: U[K] }) => + value; + +const checked1 = checkType<{ x: number; y: string }>()({ + x: 1 as number, + y: "y", + z: "z", +}); +const objChecked = { + x: 1, + y: "y", + z: "z", +}; +const checked2 = checkType<{ x: number; y: string }>()(objChecked); + +declare function fn1>(obj: { + [K in keyof T as K extends "a" ? K : never]: T[K]; +}): T; +const obj1 = { + a: 42, + b: true, +}; +const result1 = fn1(obj1); + +declare function fn2(obj: { + [K in keyof T & ("a" | "b") as K extends "a" | "c" ? K : never]: T[K]; +}): T; +const obj2 = { a: 1, b: 2, c: 3 }; +const result2 = fn2(obj2); + +declare function fn3(obj: { + [K in keyof T & ("a" | "c") as K extends "a" | "b" ? K : never]: T[K]; +}): T; +const obj3 = { a: 1, b: 2, c: 3 }; +const result3 = fn3(obj3);