diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6d9f9de3bdd8..ea86fc74de347 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13647,6 +13647,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])])); } + // If the original mapped type had an intersection constraint we extract its components, + // and we make an attempt to do so even if the intersection has been reduced to a union. + // This entire process allows us to possibly retrieve the filtering type literals. + // e.g. { [K in keyof U & ("a" | "b") ] } -> "a" | "b" + function getLimitedConstraint(type: ReverseMappedType) { + const constraint = getConstraintTypeFromMappedType(type.mappedType); + if (!(constraint.flags & TypeFlags.Union || constraint.flags & TypeFlags.Intersection)) { + return; + } + const origin = (constraint.flags & TypeFlags.Union) ? (constraint as UnionType).origin : (constraint as IntersectionType); + if (!origin || !(origin.flags & TypeFlags.Intersection)) { + return; + } + const limitedConstraint = getIntersectionType((origin as IntersectionType).types.filter(t => t !== type.constraintType)); + return limitedConstraint !== neverType ? limitedConstraint : undefined; + } + function resolveReverseMappedTypeMembers(type: ReverseMappedType) { const indexInfo = getIndexInfoOfType(type.source, stringType); const modifiers = getMappedTypeModifiers(type.mappedType); @@ -13654,7 +13671,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional; const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray; const members = createSymbolTable(); + const limitedConstraint = getLimitedConstraint(type); for (const prop of getPropertiesOfType(type.source)) { + // In case of a reverse mapped type with an intersection constraint, if we were able to + // extract the filtering type literals we skip those properties that are not assignable to them, + // because the extra properties wouldn't get through the application of the mapped type anyway + if (limitedConstraint) { + const propertyNameType = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique); + if (!isTypeAssignableTo(propertyNameType, limitedConstraint)) { + continue; + } + } const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; inferredProp.declarations = prop.declarations; @@ -25665,9 +25692,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean { - if (constraintType.flags & TypeFlags.Union) { + if ((constraintType.flags & TypeFlags.Union) || (constraintType.flags & TypeFlags.Intersection)) { let result = false; - for (const type of (constraintType as UnionType).types) { + for (const type of (constraintType as (UnionType | IntersectionType)).types) { result = inferToMappedType(source, target, type) || result; } return result; diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt new file mode 100644 index 0000000000000..ec7eab991b0ed --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.errors.txt @@ -0,0 +1,225 @@ +reverseMappedTypeIntersectionConstraint.ts(19,7): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +reverseMappedTypeIntersectionConstraint.ts(32,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ entry: "foo"; states: { a: { entry: "foo"; }; }; }'. +reverseMappedTypeIntersectionConstraint.ts(43,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. +reverseMappedTypeIntersectionConstraint.ts(59,7): error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeIntersectionConstraint.ts(63,49): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeIntersectionConstraint.ts(69,7): error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. + Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. + '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. +reverseMappedTypeIntersectionConstraint.ts(74,36): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. +reverseMappedTypeIntersectionConstraint.ts(87,12): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeIntersectionConstraint.ts(98,12): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. +reverseMappedTypeIntersectionConstraint.ts(100,22): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; y: "foo"; }'. +reverseMappedTypeIntersectionConstraint.ts(113,67): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ prop: "foo"; nested: { prop: string; }; }'. +reverseMappedTypeIntersectionConstraint.ts(152,21): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. +reverseMappedTypeIntersectionConstraint.ts(164,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ types: { actors: { src: "str"; logic: () => any; }; }; invoke: { readonly src: "str"; }; }'. +reverseMappedTypeIntersectionConstraint.ts(171,3): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ invoke: { readonly src: "whatever"; }; }'. + + +==== reverseMappedTypeIntersectionConstraint.ts (14 errors) ==== + type StateConfig = { + entry?: TAction + states?: Record>; + }; + + type StateSchema = { + states?: Record; + }; + + declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, + >(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + + const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + ~~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6500 reverseMappedTypeIntersectionConstraint.ts:2:3: The expected type comes from property 'entry' which is declared here on type 'StateConfig<"foo">' + }, + }, + extra: 12, + }); + + const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ entry: "foo"; states: { a: { entry: "foo"; }; }; }'. + }); + + + // ----------------------------------------------------------------------------------------- + + const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + + const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + }); + + checked; + + // ----------------------------------------------------------------------------------------- + + interface Stuff { + field: number; + anotherField: string; + } + + function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + + doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. + + function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + ~~~~~~ +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }[]' is not assignable to type 'T[]'. +!!! error TS2322: Type '{ [K in keyof T & keyof Stuff]: T[K]; }' is not assignable to type 'T'. +!!! error TS2322: '{ [K in keyof T & keyof Stuff]: T[K]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Stuff'. + } + } + + doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ field: 1; anotherField: "a"; }'. + ]) + + // ----------------------------------------------------------------------------------------- + + type XNumber = { x: number } + + declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + + function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design + } + + foo({x: 1, y: 'foo'}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + + foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + + // ----------------------------------------------------------------------------------------- + + type NoErrWithOptProps = { x: number, y?: string } + + declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + + baz({x: 1}); + baz({x: 1, z: 123}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; }'. + baz({x: 1, y: 'foo'}); + baz({x: 1, y: 'foo', z: 123}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: 1; y: "foo"; }'. + + // ----------------------------------------------------------------------------------------- + + interface WithNestedProp { + prop: string; + nested: { + prop: string; + } + } + + declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + + const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ prop: "foo"; nested: { prop: string; }; }'. + + // ----------------------------------------------------------------------------------------- + + type IsLiteralString = string extends T ? false : true; + + type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + + interface ProvidedActor { + src: string; + logic: () => Promise; + } + + type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + + interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; + } + + type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never + } + + declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, + >(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + + const child = () => Promise.resolve("foo"); + ~~~~~~~ +!!! error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + + const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ types: { actors: { src: "str"; logic: () => any; }; }; invoke: { readonly src: "str"; }; }'. + }); + + const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type '{ invoke: { readonly src: "whatever"; }; }'. + }); + \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js new file mode 100644 index 0000000000000..a68576c793bf8 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.js @@ -0,0 +1,260 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +//// [reverseMappedTypeIntersectionConstraint.ts] +type StateConfig = { + entry?: TAction + states?: Record>; +}; + +type StateSchema = { + states?: Record; +}; + +declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + +const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); + +const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); + +checked; + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; + anotherField: string; +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + } +} + +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + +function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design +} + +foo({x: 1, y: 'foo'}); + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + +baz({x: 1}); +baz({x: 1, z: 123}); +baz({x: 1, y: 'foo'}); +baz({x: 1, y: 'foo', z: 123}); + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; + nested: { + prop: string; + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + +interface ProvidedActor { + src: string; + logic: () => Promise; +} + +type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + +interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; +} + +type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + +const child = () => Promise.resolve("foo"); + +const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 +}); + +const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); + + +//// [reverseMappedTypeIntersectionConstraint.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); +var inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); +// ----------------------------------------------------------------------------------------- +var checkType = function () { return function (value) { return value; }; }; +var checked = checkType()({ + x: 1, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); +checked; +function doStuffWithStuff(s) { + if (Math.random() > 0.5) { + return s; + } + else { + return s; + } +} +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }); +function doStuffWithStuffArr(arr) { + if (Math.random() > 0.5) { + return arr; + } + else { + return arr; + } +} +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]); +function bar(props) { + return foo(props); // no error because lack of excess property check by design +} +foo({ x: 1, y: 'foo' }); +foo(__assign({ x: 1, y: 'foo' })); // no error because lack of excess property check by design +baz({ x: 1 }); +baz({ x: 1, z: 123 }); +baz({ x: 1, y: 'foo' }); +baz({ x: 1, y: 'foo', z: 123 }); +var wnp = withNestedProp({ prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +var child = function () { return Promise.resolve("foo"); }; +var config = createXMachine({ + types: {}, + invoke: { + src: "str", + }, + extra: 10 +}); +var config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols new file mode 100644 index 0000000000000..12cb8664c8409 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.symbols @@ -0,0 +1,491 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +=== reverseMappedTypeIntersectionConstraint.ts === +type StateConfig = { +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + + entry?: TAction +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 44)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + + states?: Record>; +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 1, 17)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 17)) + +}; + +type StateSchema = { +>StateSchema : Symbol(StateSchema, Decl(reverseMappedTypeIntersectionConstraint.ts, 3, 2)) + + states?: Record; +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 5, 20)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>StateSchema : Symbol(StateSchema, Decl(reverseMappedTypeIntersectionConstraint.ts, 3, 2)) + +}; + +declare function createMachine< +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + TConfig extends StateConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) + + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) + +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 2)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 13)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>StateConfig : Symbol(StateConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 0, 0)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 12, 13)) +>TAction : Symbol(TAction, Decl(reverseMappedTypeIntersectionConstraint.ts, 10, 39)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 9, 31)) + +const inferredParams1 = createMachine({ +>inferredParams1 : Symbol(inferredParams1, Decl(reverseMappedTypeIntersectionConstraint.ts, 14, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 14, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 15, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeIntersectionConstraint.ts, 16, 11)) + + entry: "bar", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 17, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 20, 4)) + +}); + +const inferredParams2 = createMachine({ +>inferredParams2 : Symbol(inferredParams2, Decl(reverseMappedTypeIntersectionConstraint.ts, 24, 5)) +>createMachine : Symbol(createMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 7, 2)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 24, 39)) + + states: { +>states : Symbol(states, Decl(reverseMappedTypeIntersectionConstraint.ts, 25, 15)) + + a: { +>a : Symbol(a, Decl(reverseMappedTypeIntersectionConstraint.ts, 26, 11)) + + entry: "foo", +>entry : Symbol(entry, Decl(reverseMappedTypeIntersectionConstraint.ts, 27, 8)) + + }, + }, + extra: 12, +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 30, 4)) + +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType : Symbol(checkType, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 5)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>value : Symbol(value, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 41)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 51)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 19)) +>U : Symbol(U, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 28)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 51)) +>value : Symbol(value, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 41)) + +const checked = checkType<{x: number, y: string}>()({ +>checked : Symbol(checked, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 5)) +>checkType : Symbol(checkType, Decl(reverseMappedTypeIntersectionConstraint.ts, 37, 5)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 27)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 37)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 53)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 40, 17)) + + z: "z", // undesirable property z is *not* allowed +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 41, 9)) + +}); + +checked; +>checked : Symbol(checked, Decl(reverseMappedTypeIntersectionConstraint.ts, 39, 5)) + +// ----------------------------------------------------------------------------------------- + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) + + field: number; +>field : Symbol(Stuff.field, Decl(reverseMappedTypeIntersectionConstraint.ts, 49, 17)) + + anotherField: string; +>anotherField : Symbol(Stuff.anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 50, 18)) +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 52, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) + + if(Math.random() > 0.5) { +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return s as T +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 26)) + + } else { + return s +>s : Symbol(s, Decl(reverseMappedTypeIntersectionConstraint.ts, 54, 43)) + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) +>doStuffWithStuff : Symbol(doStuffWithStuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 52, 1)) +>field : Symbol(field, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 18)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 28)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 47)) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 61)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 54)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>Stuff : Symbol(Stuff, Decl(reverseMappedTypeIntersectionConstraint.ts, 45, 8)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 54)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) + + if(Math.random() > 0.5) { +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + return arr as T[] +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 29)) + + } else { + return arr +>arr : Symbol(arr, Decl(reverseMappedTypeIntersectionConstraint.ts, 64, 46)) + } +} + +doStuffWithStuffArr([ +>doStuffWithStuffArr : Symbol(doStuffWithStuffArr, Decl(reverseMappedTypeIntersectionConstraint.ts, 62, 61)) + + { field: 1, anotherField: 'a', extra: 123 }, +>field : Symbol(field, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 5)) +>anotherField : Symbol(anotherField, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 15)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 73, 34)) + +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 16)) + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 40)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 49)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>XNumber : Symbol(XNumber, Decl(reverseMappedTypeIntersectionConstraint.ts, 74, 2)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 21)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 49)) + +function bar(props: {x: number, y: string}) { +>bar : Symbol(bar, Decl(reverseMappedTypeIntersectionConstraint.ts, 80, 93)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 13)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 21)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 31)) + + return foo(props); // no error because lack of excess property check by design +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 82, 13)) +} + +foo({x: 1, y: 'foo'}); +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 86, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 86, 10)) + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design +>foo : Symbol(foo, Decl(reverseMappedTypeIntersectionConstraint.ts, 78, 28)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 9)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 14)) + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 26)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 37)) + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 50)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 59)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>NoErrWithOptProps : Symbol(NoErrWithOptProps, Decl(reverseMappedTypeIntersectionConstraint.ts, 88, 27)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 21)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 94, 59)) + +baz({x: 1}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 96, 5)) + +baz({x: 1, z: 123}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 97, 5)) +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 97, 10)) + +baz({x: 1, y: 'foo'}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 98, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 98, 10)) + +baz({x: 1, y: 'foo', z: 123}); +>baz : Symbol(baz, Decl(reverseMappedTypeIntersectionConstraint.ts, 92, 50)) +>x : Symbol(x, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 5)) +>y : Symbol(y, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 10)) +>z : Symbol(z, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 20)) + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) + + prop: string; +>prop : Symbol(WithNestedProp.prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 103, 26)) + + nested: { +>nested : Symbol(WithNestedProp.nested, Decl(reverseMappedTypeIntersectionConstraint.ts, 104, 15)) + + prop: string; +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 105, 11)) + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 108, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) +>props : Symbol(props, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 58)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 67)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>WithNestedProp : Symbol(WithNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 99, 30)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 67)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 110, 32)) + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +>wnp : Symbol(wnp, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 5)) +>withNestedProp : Symbol(withNestedProp, Decl(reverseMappedTypeIntersectionConstraint.ts, 108, 1)) +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 28)) +>nested : Symbol(nested, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 40)) +>prop : Symbol(prop, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 50)) +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 65)) + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 79)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 21)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 21)) + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } +>DeepWritable : Symbol(DeepWritable, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 73)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 61)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>DeepWritable : Symbol(DeepWritable, Decl(reverseMappedTypeIntersectionConstraint.ts, 116, 73)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 18)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 61)) + +interface ProvidedActor { +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + + src: string; +>src : Symbol(ProvidedActor.src, Decl(reverseMappedTypeIntersectionConstraint.ts, 120, 25)) + + logic: () => Promise; +>logic : Symbol(ProvidedActor.logic, Decl(reverseMappedTypeIntersectionConstraint.ts, 121, 14)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +} + +type DistributeActors = TActor extends { src: infer TSrc } +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeIntersectionConstraint.ts, 123, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 22)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 22)) +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 48)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 59)) + + ? { + src: TSrc; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 126, 5)) +>TSrc : Symbol(TSrc, Decl(reverseMappedTypeIntersectionConstraint.ts, 125, 59)) + } + : never; + +interface MachineConfig { +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + + types?: { +>types : Symbol(MachineConfig.types, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 55)) + + actors?: TActor; +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 132, 11)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + }; + invoke: IsLiteralString extends true +>invoke : Symbol(MachineConfig.invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 134, 4)) +>IsLiteralString : Symbol(IsLiteralString, Decl(reverseMappedTypeIntersectionConstraint.ts, 112, 79)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + ? DistributeActors +>DistributeActors : Symbol(DistributeActors, Decl(reverseMappedTypeIntersectionConstraint.ts, 123, 1)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 131, 24)) + + : { + src: string; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 137, 7)) + + }; +} + +type NoExtra = { +>NoExtra : Symbol(NoExtra, Decl(reverseMappedTypeIntersectionConstraint.ts, 140, 1)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) + + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>T : Symbol(T, Decl(reverseMappedTypeIntersectionConstraint.ts, 142, 13)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 143, 3)) +} + +declare function createXMachine< +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + const TConfig extends MachineConfig, +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 147, 46)) + + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>TActor : Symbol(TActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 147, 46)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>types : Symbol(types, Decl(reverseMappedTypeIntersectionConstraint.ts, 148, 50)) +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 148, 59)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>ProvidedActor : Symbol(ProvidedActor, Decl(reverseMappedTypeIntersectionConstraint.ts, 118, 96)) + +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 2)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 12)) +>MachineConfig : Symbol(MachineConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 129, 10)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) +>K : Symbol(K, Decl(reverseMappedTypeIntersectionConstraint.ts, 149, 12)) +>TConfig : Symbol(TConfig, Decl(reverseMappedTypeIntersectionConstraint.ts, 146, 32)) + +const child = () => Promise.resolve("foo"); +>child : Symbol(child, Decl(reverseMappedTypeIntersectionConstraint.ts, 151, 5)) + +const config = createXMachine({ +>config : Symbol(config, Decl(reverseMappedTypeIntersectionConstraint.ts, 153, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + types: {} as { +>types : Symbol(types, Decl(reverseMappedTypeIntersectionConstraint.ts, 153, 31)) + + actors: { +>actors : Symbol(actors, Decl(reverseMappedTypeIntersectionConstraint.ts, 154, 16)) + + src: "str"; +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 155, 13)) + + logic: typeof child; +>logic : Symbol(logic, Decl(reverseMappedTypeIntersectionConstraint.ts, 156, 17)) +>child : Symbol(child, Decl(reverseMappedTypeIntersectionConstraint.ts, 151, 5)) + + }; + }, + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 159, 4)) + + src: "str", +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 160, 11)) + + }, + extra: 10 +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 162, 4)) + +}); + +const config2 = createXMachine({ +>config2 : Symbol(config2, Decl(reverseMappedTypeIntersectionConstraint.ts, 166, 5)) +>createXMachine : Symbol(createXMachine, Decl(reverseMappedTypeIntersectionConstraint.ts, 144, 1)) + + invoke: { +>invoke : Symbol(invoke, Decl(reverseMappedTypeIntersectionConstraint.ts, 166, 32)) + + src: "whatever", +>src : Symbol(src, Decl(reverseMappedTypeIntersectionConstraint.ts, 167, 11)) + + }, + extra: 10 +>extra : Symbol(extra, Decl(reverseMappedTypeIntersectionConstraint.ts, 169, 4)) + +}); + diff --git a/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types new file mode 100644 index 0000000000000..43b568dd83d87 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeIntersectionConstraint.types @@ -0,0 +1,461 @@ +//// [tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts] //// + +=== reverseMappedTypeIntersectionConstraint.ts === +type StateConfig = { +>StateConfig : StateConfig + + entry?: TAction +>entry : TAction | undefined + + states?: Record>; +>states : Record> | undefined + +}; + +type StateSchema = { +>StateSchema : { states?: Record | undefined; } + + states?: Record; +>states : Record | undefined + +}; + +declare function createMachine< +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] + + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; +>config : { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; } + +const inferredParams1 = createMachine({ +>inferredParams1 : ["foo", StateConfig<"foo">] +>createMachine({ entry: "foo", states: { a: { entry: "bar", }, }, extra: 12,}) : ["foo", StateConfig<"foo">] +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] +>{ entry: "foo", states: { a: { entry: "bar", }, }, extra: 12,} : { entry: "foo"; states: { a: { entry: "bar"; }; }; extra: number; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + states: { +>states : { a: { entry: "bar"; }; } +>{ a: { entry: "bar", }, } : { a: { entry: "bar"; }; } + + a: { +>a : { entry: "bar"; } +>{ entry: "bar", } : { entry: "bar"; } + + entry: "bar", +>entry : "bar" +>"bar" : "bar" + + }, + }, + extra: 12, +>extra : number +>12 : 12 + +}); + +const inferredParams2 = createMachine({ +>inferredParams2 : ["foo", { entry: "foo"; states: { a: { entry: "foo"; }; }; }] +>createMachine({ entry: "foo", states: { a: { entry: "foo", }, }, extra: 12,}) : ["foo", { entry: "foo"; states: { a: { entry: "foo"; }; }; }] +>createMachine : , TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K]; }) => [TAction, TConfig] +>{ entry: "foo", states: { a: { entry: "foo", }, }, extra: 12,} : { entry: "foo"; states: { a: { entry: "foo"; }; }; extra: number; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + states: { +>states : { a: { entry: "foo"; }; } +>{ a: { entry: "foo", }, } : { a: { entry: "foo"; }; } + + a: { +>a : { entry: "foo"; } +>{ entry: "foo", } : { entry: "foo"; } + + entry: "foo", +>entry : "foo" +>"foo" : "foo" + + }, + }, + extra: 12, +>extra : number +>12 : 12 + +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>() => (value: { [K in keyof U & keyof T]: U[K] }) => value : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>(value: { [K in keyof U & keyof T]: U[K] }) => value : (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } + +const checked = checkType<{x: number, y: string}>()({ +>checked : { x: number; y: "y"; } +>checkType<{x: number, y: string}>()({ x: 1 as number, y: "y", z: "z", // undesirable property z is *not* allowed}) : { x: number; y: "y"; } +>checkType<{x: number, y: string}>() : (value: { [K in keyof U & ("x" | "y")]: U[K]; }) => { [K in keyof U & ("x" | "y")]: U[K]; } +>checkType : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>x : number +>y : string +>{ x: 1 as number, y: "y", z: "z", // undesirable property z is *not* allowed} : { x: number; y: "y"; z: string; } + + x: 1 as number, +>x : number +>1 as number : number +>1 : 1 + + y: "y", +>y : "y" +>"y" : "y" + + z: "z", // undesirable property z is *not* allowed +>z : string +>"z" : "z" + +}); + +checked; +>checked : { x: number; y: "y"; } + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; +>field : number + + anotherField: string; +>anotherField : string +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { +>doStuffWithStuff : (s: { [K in keyof T & keyof Stuff]: T[K]; }) => T +>s : { [K in keyof T & keyof Stuff]: T[K]; } + + if(Math.random() > 0.5) { +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + return s as T +>s as T : T +>s : { [K in keyof T & keyof Stuff]: T[K]; } + + } else { + return s +>s : { [K in keyof T & keyof Stuff]: T[K]; } + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) +>doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) : { field: 1; anotherField: "a"; } +>doStuffWithStuff : (s: { [K in keyof T & keyof Stuff]: T[K]; }) => T +>{ field: 1, anotherField: 'a', extra: 123 } : { field: 1; anotherField: "a"; extra: number; } +>field : 1 +>1 : 1 +>anotherField : "a" +>'a' : "a" +>extra : number +>123 : 123 + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { +>doStuffWithStuffArr : (arr: { [K in keyof T & keyof Stuff]: T[K]; }[]) => T[] +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + + if(Math.random() > 0.5) { +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + return arr as T[] +>arr as T[] : T[] +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + + } else { + return arr +>arr : { [K in keyof T & keyof Stuff]: T[K]; }[] + } +} + +doStuffWithStuffArr([ +>doStuffWithStuffArr([ { field: 1, anotherField: 'a', extra: 123 },]) : { field: 1; anotherField: "a"; }[] +>doStuffWithStuffArr : (arr: { [K in keyof T & keyof Stuff]: T[K]; }[]) => T[] +>[ { field: 1, anotherField: 'a', extra: 123 },] : { field: 1; anotherField: "a"; extra: number; }[] + + { field: 1, anotherField: 'a', extra: 123 }, +>{ field: 1, anotherField: 'a', extra: 123 } : { field: 1; anotherField: "a"; extra: number; } +>field : 1 +>1 : 1 +>anotherField : "a" +>'a' : "a" +>extra : number +>123 : 123 + +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } +>XNumber : { x: number; } +>x : number + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>props : { [K in keyof T & "x"]: T[K]; } + +function bar(props: {x: number, y: string}) { +>bar : (props: { x: number; y: string;}) => void +>props : { x: number; y: string; } +>x : number +>y : string + + return foo(props); // no error because lack of excess property check by design +>foo(props) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>props : { x: number; y: string; } +} + +foo({x: 1, y: 'foo'}); +>foo({x: 1, y: 'foo'}) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design +>foo({...{x: 1, y: 'foo'}}) : void +>foo : (props: { [K in keyof T & "x"]: T[K]; }) => void +>{...{x: 1, y: 'foo'}} : { x: 1; y: string; } +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } +>NoErrWithOptProps : { x: number; y?: string | undefined; } +>x : number +>y : string | undefined + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>props : { [K in keyof T & keyof NoErrWithOptProps]: T[K]; } + +baz({x: 1}); +>baz({x: 1}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1} : { x: 1; } +>x : 1 +>1 : 1 + +baz({x: 1, z: 123}); +>baz({x: 1, z: 123}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, z: 123} : { x: 1; z: number; } +>x : 1 +>1 : 1 +>z : number +>123 : 123 + +baz({x: 1, y: 'foo'}); +>baz({x: 1, y: 'foo'}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, y: 'foo'} : { x: 1; y: "foo"; } +>x : 1 +>1 : 1 +>y : "foo" +>'foo' : "foo" + +baz({x: 1, y: 'foo', z: 123}); +>baz({x: 1, y: 'foo', z: 123}) : void +>baz : (props: { [K in keyof T & keyof NoErrWithOptProps]: T[K]; }) => void +>{x: 1, y: 'foo', z: 123} : { x: 1; y: "foo"; z: number; } +>x : 1 +>1 : 1 +>y : "foo" +>'foo' : "foo" +>z : number +>123 : 123 + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; +>prop : string + + nested: { +>nested : { prop: string; } + + prop: string; +>prop : string + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; +>withNestedProp : (props: { [K in keyof T & keyof WithNestedProp]: T[K]; }) => T +>props : { [K in keyof T & keyof WithNestedProp]: T[K]; } + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); +>wnp : { prop: "foo"; nested: { prop: string; }; } +>withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }) : { prop: "foo"; nested: { prop: string; }; } +>withNestedProp : (props: { [K in keyof T & keyof WithNestedProp]: T[K]; }) => T +>{prop: 'foo', nested: { prop: 'bar' }, extra: 10 } : { prop: "foo"; nested: { prop: string; }; extra: number; } +>prop : "foo" +>'foo' : "foo" +>nested : { prop: string; } +>{ prop: 'bar' } : { prop: string; } +>prop : string +>'bar' : "bar" +>extra : number +>10 : 10 + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; +>IsLiteralString : IsLiteralString +>false : false +>true : true + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } +>DeepWritable : DeepWritable + +interface ProvidedActor { + src: string; +>src : string + + logic: () => Promise; +>logic : () => Promise +} + +type DistributeActors = TActor extends { src: infer TSrc } +>DistributeActors : DistributeActors +>src : TSrc + + ? { + src: TSrc; +>src : TSrc + } + : never; + +interface MachineConfig { + types?: { +>types : { actors?: TActor | undefined; } | undefined + + actors?: TActor; +>actors : TActor | undefined + + }; + invoke: IsLiteralString extends true +>invoke : IsLiteralString extends true ? DistributeActors : { src: string; } +>true : true + + ? DistributeActors + : { + src: string; +>src : string + + }; +} + +type NoExtra = { +>NoExtra : NoExtra + + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor;}; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig + + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>types : { actors: ProvidedActor; } +>actors : ProvidedActor + +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; +>config : { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; } + +const child = () => Promise.resolve("foo"); +>child : () => any +>() => Promise.resolve("foo") : () => any +>Promise.resolve("foo") : any +>Promise.resolve : any +>Promise : any +>resolve : any +>"foo" : "foo" + +const config = createXMachine({ +>config : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { readonly src: "str"; }; } +>createXMachine({ types: {} as { actors: { src: "str"; logic: typeof child; }; }, invoke: { src: "str", }, extra: 10}) : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { readonly src: "str"; }; } +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig +>{ types: {} as { actors: { src: "str"; logic: typeof child; }; }, invoke: { src: "str", }, extra: 10} : { types: { actors: { src: "str"; logic: typeof child;}; }; invoke: { src: "str"; }; extra: number; } + + types: {} as { +>types : { actors: { src: "str"; logic: typeof child;}; } +>{} as { actors: { src: "str"; logic: typeof child; }; } : { actors: { src: "str"; logic: typeof child;}; } +>{} : {} + + actors: { +>actors : { src: "str"; logic: typeof child; } + + src: "str"; +>src : "str" + + logic: typeof child; +>logic : () => any +>child : () => any + + }; + }, + invoke: { +>invoke : { src: "str"; } +>{ src: "str", } : { src: "str"; } + + src: "str", +>src : "str" +>"str" : "str" + + }, + extra: 10 +>extra : number +>10 : 10 + +}); + +const config2 = createXMachine({ +>config2 : { invoke: { readonly src: "whatever"; }; } +>createXMachine({ invoke: { src: "whatever", }, extra: 10}) : { invoke: { readonly src: "whatever"; }; } +>createXMachine : , TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor; }; } ? TConfig["types"]["actors"] : ProvidedActor>(config: { [K in keyof MachineConfig & keyof TConfig]: TConfig[K]; }) => TConfig +>{ invoke: { src: "whatever", }, extra: 10} : { invoke: { src: "whatever"; }; extra: number; } + + invoke: { +>invoke : { src: "whatever"; } +>{ src: "whatever", } : { src: "whatever"; } + + src: "whatever", +>src : "whatever" +>"whatever" : "whatever" + + }, + extra: 10 +>extra : number +>10 : 10 + +}); + diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt new file mode 100644 index 0000000000000..dc6dc8fa3a331 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.errors.txt @@ -0,0 +1,24 @@ +reverseMappedTypeLimitedConstraint.ts(5,13): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. +reverseMappedTypeLimitedConstraint.ts(14,3): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + + +==== reverseMappedTypeLimitedConstraint.ts (2 errors) ==== + type XNumber_ = { x: number } + + declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + + foo_({x: 1, y: 'foo'}); + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: 1; }'. + + // ----------------------------------------------------------------------------------------- + + const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + + const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", + ~ +!!! error TS2353: Object literal may only specify known properties, and 'z' does not exist in type '{ x: number; y: "y"; }'. + }); \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js new file mode 100644 index 0000000000000..0be7aa8d6a423 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +//// [reverseMappedTypeLimitedConstraint.ts] +type XNumber_ = { x: number } + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + +foo_({x: 1, y: 'foo'}); + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", +}); + +//// [reverseMappedTypeLimitedConstraint.js] +foo_({ x: 1, y: 'foo' }); +// ----------------------------------------------------------------------------------------- +var checkType_ = function () { return function (value) { return value; }; }; +var checked_ = checkType_()({ + x: 1, + y: "y", + z: "z", +}); diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols new file mode 100644 index 0000000000000..5c81507278445 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.symbols @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +=== reverseMappedTypeLimitedConstraint.ts === +type XNumber_ = { x: number } +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 17)) + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; +>foo_ : Symbol(foo_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>props : Symbol(props, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 42)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 51)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>XNumber_ : Symbol(XNumber_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 51)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 2, 22)) + +foo_({x: 1, y: 'foo'}); +>foo_ : Symbol(foo_, Decl(reverseMappedTypeLimitedConstraint.ts, 0, 29)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 4, 6)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 4, 11)) + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType_ : Symbol(checkType_, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 5)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 42)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 52)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>T : Symbol(T, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 20)) +>U : Symbol(U, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 29)) +>K : Symbol(K, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 52)) +>value : Symbol(value, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 42)) + +const checked_ = checkType_<{x: number, y: string}>()({ +>checked_ : Symbol(checked_, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 5)) +>checkType_ : Symbol(checkType_, Decl(reverseMappedTypeLimitedConstraint.ts, 8, 5)) +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 29)) +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 39)) + + x: 1 as number, +>x : Symbol(x, Decl(reverseMappedTypeLimitedConstraint.ts, 10, 55)) + + y: "y", +>y : Symbol(y, Decl(reverseMappedTypeLimitedConstraint.ts, 11, 17)) + + z: "z", +>z : Symbol(z, Decl(reverseMappedTypeLimitedConstraint.ts, 12, 9)) + +}); diff --git a/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types new file mode 100644 index 0000000000000..821d7685fcccd --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeLimitedConstraint.types @@ -0,0 +1,52 @@ +//// [tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts] //// + +=== reverseMappedTypeLimitedConstraint.ts === +type XNumber_ = { x: number } +>XNumber_ : { x: number; } +>x : number + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; +>foo_ : (props: { [K in keyof T & "x"]: T[K]; }) => T +>props : { [K in keyof T & "x"]: T[K]; } + +foo_({x: 1, y: 'foo'}); +>foo_({x: 1, y: 'foo'}) : { x: 1; } +>foo_ : (props: { [K in keyof T & "x"]: T[K]; }) => T +>{x: 1, y: 'foo'} : { x: 1; y: string; } +>x : 1 +>1 : 1 +>y : string +>'foo' : "foo" + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; +>checkType_ : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>() => (value: { [K in keyof U & keyof T]: U[K] }) => value : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>(value: { [K in keyof U & keyof T]: U[K] }) => value : (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } +>value : { [K in keyof U & keyof T]: U[K]; } + +const checked_ = checkType_<{x: number, y: string}>()({ +>checked_ : { x: number; y: "y"; } +>checkType_<{x: number, y: string}>()({ x: 1 as number, y: "y", z: "z",}) : { x: number; y: "y"; } +>checkType_<{x: number, y: string}>() : (value: { [K in keyof U & ("x" | "y")]: U[K]; }) => { [K in keyof U & ("x" | "y")]: U[K]; } +>checkType_ : () => (value: { [K in keyof U & keyof T]: U[K]; }) => { [K in keyof U & keyof T]: U[K]; } +>x : number +>y : string +>{ x: 1 as number, y: "y", z: "z",} : { x: number; y: "y"; z: string; } + + x: 1 as number, +>x : number +>1 as number : number +>1 : 1 + + y: "y", +>y : "y" +>"y" : "y" + + z: "z", +>z : string +>"z" : "z" + +}); diff --git a/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts b/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts new file mode 100644 index 0000000000000..e565549791177 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeIntersectionConstraint.ts @@ -0,0 +1,174 @@ +// @strict: true + +type StateConfig = { + entry?: TAction + states?: Record>; +}; + +type StateSchema = { + states?: Record; +}; + +declare function createMachine< + TConfig extends StateConfig, + TAction extends string = TConfig["entry"] extends string ? TConfig["entry"] : string, +>(config: { [K in keyof TConfig & keyof StateConfig]: TConfig[K] }): [TAction, TConfig]; + +const inferredParams1 = createMachine({ + entry: "foo", + states: { + a: { + entry: "bar", + }, + }, + extra: 12, +}); + +const inferredParams2 = createMachine({ + entry: "foo", + states: { + a: { + entry: "foo", + }, + }, + extra: 12, +}); + + +// ----------------------------------------------------------------------------------------- + +const checkType = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked = checkType<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", // undesirable property z is *not* allowed +}); + +checked; + +// ----------------------------------------------------------------------------------------- + +interface Stuff { + field: number; + anotherField: string; +} + +function doStuffWithStuff(s: { [K in keyof T & keyof Stuff]: T[K] } ): T { + if(Math.random() > 0.5) { + return s as T + } else { + return s + } +} + +doStuffWithStuff({ field: 1, anotherField: 'a', extra: 123 }) + +function doStuffWithStuffArr(arr: { [K in keyof T & keyof Stuff]: T[K] }[]): T[] { + if(Math.random() > 0.5) { + return arr as T[] + } else { + return arr + } +} + +doStuffWithStuffArr([ + { field: 1, anotherField: 'a', extra: 123 }, +]) + +// ----------------------------------------------------------------------------------------- + +type XNumber = { x: number } + +declare function foo(props: {[K in keyof T & keyof XNumber]: T[K]}): void; + +function bar(props: {x: number, y: string}) { + return foo(props); // no error because lack of excess property check by design +} + +foo({x: 1, y: 'foo'}); + +foo({...{x: 1, y: 'foo'}}); // no error because lack of excess property check by design + +// ----------------------------------------------------------------------------------------- + +type NoErrWithOptProps = { x: number, y?: string } + +declare function baz(props: {[K in keyof T & keyof NoErrWithOptProps]: T[K]}): void; + +baz({x: 1}); +baz({x: 1, z: 123}); +baz({x: 1, y: 'foo'}); +baz({x: 1, y: 'foo', z: 123}); + +// ----------------------------------------------------------------------------------------- + +interface WithNestedProp { + prop: string; + nested: { + prop: string; + } +} + +declare function withNestedProp(props: {[K in keyof T & keyof WithNestedProp]: T[K]}): T; + +const wnp = withNestedProp({prop: 'foo', nested: { prop: 'bar' }, extra: 10 }); + +// ----------------------------------------------------------------------------------------- + +type IsLiteralString = string extends T ? false : true; + +type DeepWritable = T extends Function ? T : { -readonly [K in keyof T]: DeepWritable } + +interface ProvidedActor { + src: string; + logic: () => Promise; +} + +type DistributeActors = TActor extends { src: infer TSrc } + ? { + src: TSrc; + } + : never; + +interface MachineConfig { + types?: { + actors?: TActor; + }; + invoke: IsLiteralString extends true + ? DistributeActors + : { + src: string; + }; +} + +type NoExtra = { + [K in keyof T]: K extends keyof MachineConfig ? T[K] : never +} + +declare function createXMachine< + const TConfig extends MachineConfig, + TActor extends ProvidedActor = TConfig extends { types: { actors: ProvidedActor} } ? TConfig["types"]["actors"] : ProvidedActor, +>(config: {[K in keyof MachineConfig & keyof TConfig]: TConfig[K] }): TConfig; + +const child = () => Promise.resolve("foo"); + +const config = createXMachine({ + types: {} as { + actors: { + src: "str"; + logic: typeof child; + }; + }, + invoke: { + src: "str", + }, + extra: 10 +}); + +const config2 = createXMachine({ + invoke: { + src: "whatever", + }, + extra: 10 +}); diff --git a/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts b/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts new file mode 100644 index 0000000000000..7618ae65046a9 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeLimitedConstraint.ts @@ -0,0 +1,15 @@ +type XNumber_ = { x: number } + +declare function foo_(props: {[K in keyof T & keyof XNumber_]: T[K]}): T; + +foo_({x: 1, y: 'foo'}); + +// ----------------------------------------------------------------------------------------- + +const checkType_ = () => (value: { [K in keyof U & keyof T]: U[K] }) => value; + +const checked_ = checkType_<{x: number, y: string}>()({ + x: 1 as number, + y: "y", + z: "z", +}); \ No newline at end of file