From 0a975626ecdffe557ba9be0c47c8ff63b5fce90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 8 Mar 2024 23:21:00 +0100 Subject: [PATCH] Remove `missingType` when inferring from properties in EOPT (#57447) --- src/compiler/checker.ts | 7 +- .../inferenceExactOptionalProperties1.symbols | 10 + .../inferenceExactOptionalProperties1.types | 9 + ...ferenceExactOptionalProperties2.errors.txt | 79 +++++++ .../inferenceExactOptionalProperties2.symbols | 197 ++++++++++++++++++ .../inferenceExactOptionalProperties2.types | 158 ++++++++++++++ .../inferenceExactOptionalProperties1.ts | 5 + .../inferenceExactOptionalProperties2.ts | 76 +++++++ 8 files changed, 539 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/inferenceExactOptionalProperties1.symbols create mode 100644 tests/baselines/reference/inferenceExactOptionalProperties1.types create mode 100644 tests/baselines/reference/inferenceExactOptionalProperties2.errors.txt create mode 100644 tests/baselines/reference/inferenceExactOptionalProperties2.symbols create mode 100644 tests/baselines/reference/inferenceExactOptionalProperties2.types create mode 100644 tests/cases/compiler/inferenceExactOptionalProperties1.ts create mode 100644 tests/cases/compiler/inferenceExactOptionalProperties2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f175b680655..55e5378b02b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26179,7 +26179,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const targetProp of properties) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); if (sourceProp && !some(sourceProp.declarations, hasSkipDirectInferenceFlag)) { - inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); + inferFromTypes( + removeMissingType(getTypeOfSymbol(sourceProp), !!(sourceProp.flags & SymbolFlags.Optional)), + removeMissingType(getTypeOfSymbol(targetProp), !!(targetProp.flags & SymbolFlags.Optional)), + ); } } } @@ -30575,7 +30578,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (t.flags & TypeFlags.StructuredType) { const prop = getPropertyOfType(t, name); if (prop) { - return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop && prop.flags & SymbolFlags.Optional)); + return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional)); } if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); diff --git a/tests/baselines/reference/inferenceExactOptionalProperties1.symbols b/tests/baselines/reference/inferenceExactOptionalProperties1.symbols new file mode 100644 index 00000000000..c2347c4d47a --- /dev/null +++ b/tests/baselines/reference/inferenceExactOptionalProperties1.symbols @@ -0,0 +1,10 @@ +//// [tests/cases/compiler/inferenceExactOptionalProperties1.ts] //// + +=== inferenceExactOptionalProperties1.ts === +type Test1 = { prop?: never } extends { prop?: infer T } ? T : false; // never +>Test1 : Symbol(Test1, Decl(inferenceExactOptionalProperties1.ts, 0, 0)) +>prop : Symbol(prop, Decl(inferenceExactOptionalProperties1.ts, 0, 14)) +>prop : Symbol(prop, Decl(inferenceExactOptionalProperties1.ts, 0, 39)) +>T : Symbol(T, Decl(inferenceExactOptionalProperties1.ts, 0, 52)) +>T : Symbol(T, Decl(inferenceExactOptionalProperties1.ts, 0, 52)) + diff --git a/tests/baselines/reference/inferenceExactOptionalProperties1.types b/tests/baselines/reference/inferenceExactOptionalProperties1.types new file mode 100644 index 00000000000..31c179a950d --- /dev/null +++ b/tests/baselines/reference/inferenceExactOptionalProperties1.types @@ -0,0 +1,9 @@ +//// [tests/cases/compiler/inferenceExactOptionalProperties1.ts] //// + +=== inferenceExactOptionalProperties1.ts === +type Test1 = { prop?: never } extends { prop?: infer T } ? T : false; // never +>Test1 : never +>prop : undefined +>prop : T | undefined +>false : false + diff --git a/tests/baselines/reference/inferenceExactOptionalProperties2.errors.txt b/tests/baselines/reference/inferenceExactOptionalProperties2.errors.txt new file mode 100644 index 00000000000..e00df1952aa --- /dev/null +++ b/tests/baselines/reference/inferenceExactOptionalProperties2.errors.txt @@ -0,0 +1,79 @@ +inferenceExactOptionalProperties2.ts(64,11): error TS2345: Argument of type '"alarm"' is not assignable to parameter of type '"counter"'. + + +==== inferenceExactOptionalProperties2.ts (1 errors) ==== + type Values = T[keyof T]; + + type EventObject = { + type: string; + }; + + interface ActorLogic { + transition: (ev: TEvent) => unknown; + } + + type UnknownActorLogic = ActorLogic; + + interface ProvidedActor { + src: string; + logic: UnknownActorLogic; + } + + interface ActionFunction { + (): void; + _out_TActor?: TActor; + } + + interface AssignAction { + (): void; + _out_TActor?: TActor; + } + + interface MachineConfig { + entry?: ActionFunction; + } + + declare function assign( + _: (spawn: (actor: TActor["src"]) => void) => {}, + ): AssignAction; + + type ToProvidedActor> = + Values<{ + [K in keyof TActors & string]: { + src: K; + logic: TActors[K]; + }; + }>; + + declare function setup< + TActors extends Record = {}, + >(implementations?: { + actors?: { [K in keyof TActors]: TActors[K] }; + }): { + createMachine: < + const TConfig extends MachineConfig>, + >( + config: TConfig, + ) => void; + }; + + declare const counterLogic: ActorLogic<{ type: "INCREMENT" }>; + + // example usage + setup({ + actors: { counter: counterLogic }, + }).createMachine({ + entry: assign((spawn) => { + spawn("counter"); // ok + spawn("alarm"); // error + ~~~~~~~ +!!! error TS2345: Argument of type '"alarm"' is not assignable to parameter of type '"counter"'. + return {}; + }), + }); + + // no provided actors, `assign` should still work + setup().createMachine({ + entry: assign(() => ({})), + }); + \ No newline at end of file diff --git a/tests/baselines/reference/inferenceExactOptionalProperties2.symbols b/tests/baselines/reference/inferenceExactOptionalProperties2.symbols new file mode 100644 index 00000000000..4afdcd98754 --- /dev/null +++ b/tests/baselines/reference/inferenceExactOptionalProperties2.symbols @@ -0,0 +1,197 @@ +//// [tests/cases/compiler/inferenceExactOptionalProperties2.ts] //// + +=== inferenceExactOptionalProperties2.ts === +type Values = T[keyof T]; +>Values : Symbol(Values, Decl(inferenceExactOptionalProperties2.ts, 0, 0)) +>T : Symbol(T, Decl(inferenceExactOptionalProperties2.ts, 0, 12)) +>T : Symbol(T, Decl(inferenceExactOptionalProperties2.ts, 0, 12)) +>T : Symbol(T, Decl(inferenceExactOptionalProperties2.ts, 0, 12)) + +type EventObject = { +>EventObject : Symbol(EventObject, Decl(inferenceExactOptionalProperties2.ts, 0, 28)) + + type: string; +>type : Symbol(type, Decl(inferenceExactOptionalProperties2.ts, 2, 20)) + +}; + +interface ActorLogic { +>ActorLogic : Symbol(ActorLogic, Decl(inferenceExactOptionalProperties2.ts, 4, 2)) +>TEvent : Symbol(TEvent, Decl(inferenceExactOptionalProperties2.ts, 6, 21)) +>EventObject : Symbol(EventObject, Decl(inferenceExactOptionalProperties2.ts, 0, 28)) + + transition: (ev: TEvent) => unknown; +>transition : Symbol(ActorLogic.transition, Decl(inferenceExactOptionalProperties2.ts, 6, 50)) +>ev : Symbol(ev, Decl(inferenceExactOptionalProperties2.ts, 7, 15)) +>TEvent : Symbol(TEvent, Decl(inferenceExactOptionalProperties2.ts, 6, 21)) +} + +type UnknownActorLogic = ActorLogic; +>UnknownActorLogic : Symbol(UnknownActorLogic, Decl(inferenceExactOptionalProperties2.ts, 8, 1)) +>ActorLogic : Symbol(ActorLogic, Decl(inferenceExactOptionalProperties2.ts, 4, 2)) + +interface ProvidedActor { +>ProvidedActor : Symbol(ProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 10, 43)) + + src: string; +>src : Symbol(ProvidedActor.src, Decl(inferenceExactOptionalProperties2.ts, 12, 25)) + + logic: UnknownActorLogic; +>logic : Symbol(ProvidedActor.logic, Decl(inferenceExactOptionalProperties2.ts, 13, 14)) +>UnknownActorLogic : Symbol(UnknownActorLogic, Decl(inferenceExactOptionalProperties2.ts, 8, 1)) +} + +interface ActionFunction { +>ActionFunction : Symbol(ActionFunction, Decl(inferenceExactOptionalProperties2.ts, 15, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 17, 25)) +>ProvidedActor : Symbol(ProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 10, 43)) + + (): void; + _out_TActor?: TActor; +>_out_TActor : Symbol(ActionFunction._out_TActor, Decl(inferenceExactOptionalProperties2.ts, 18, 11)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 17, 25)) +} + +interface AssignAction { +>AssignAction : Symbol(AssignAction, Decl(inferenceExactOptionalProperties2.ts, 20, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 22, 23)) +>ProvidedActor : Symbol(ProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 10, 43)) + + (): void; + _out_TActor?: TActor; +>_out_TActor : Symbol(AssignAction._out_TActor, Decl(inferenceExactOptionalProperties2.ts, 23, 11)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 22, 23)) +} + +interface MachineConfig { +>MachineConfig : Symbol(MachineConfig, Decl(inferenceExactOptionalProperties2.ts, 25, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 27, 24)) +>ProvidedActor : Symbol(ProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 10, 43)) + + entry?: ActionFunction; +>entry : Symbol(MachineConfig.entry, Decl(inferenceExactOptionalProperties2.ts, 27, 55)) +>ActionFunction : Symbol(ActionFunction, Decl(inferenceExactOptionalProperties2.ts, 15, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 27, 24)) +} + +declare function assign( +>assign : Symbol(assign, Decl(inferenceExactOptionalProperties2.ts, 29, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 31, 24)) +>ProvidedActor : Symbol(ProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 10, 43)) + + _: (spawn: (actor: TActor["src"]) => void) => {}, +>_ : Symbol(_, Decl(inferenceExactOptionalProperties2.ts, 31, 54)) +>spawn : Symbol(spawn, Decl(inferenceExactOptionalProperties2.ts, 32, 6)) +>actor : Symbol(actor, Decl(inferenceExactOptionalProperties2.ts, 32, 14)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 31, 24)) + +): AssignAction; +>AssignAction : Symbol(AssignAction, Decl(inferenceExactOptionalProperties2.ts, 20, 1)) +>TActor : Symbol(TActor, Decl(inferenceExactOptionalProperties2.ts, 31, 24)) + +type ToProvidedActor> = +>ToProvidedActor : Symbol(ToProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 33, 24)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 35, 21)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>UnknownActorLogic : Symbol(UnknownActorLogic, Decl(inferenceExactOptionalProperties2.ts, 8, 1)) + + Values<{ +>Values : Symbol(Values, Decl(inferenceExactOptionalProperties2.ts, 0, 0)) + + [K in keyof TActors & string]: { +>K : Symbol(K, Decl(inferenceExactOptionalProperties2.ts, 37, 5)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 35, 21)) + + src: K; +>src : Symbol(src, Decl(inferenceExactOptionalProperties2.ts, 37, 36)) +>K : Symbol(K, Decl(inferenceExactOptionalProperties2.ts, 37, 5)) + + logic: TActors[K]; +>logic : Symbol(logic, Decl(inferenceExactOptionalProperties2.ts, 38, 13)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 35, 21)) +>K : Symbol(K, Decl(inferenceExactOptionalProperties2.ts, 37, 5)) + + }; + }>; + +declare function setup< +>setup : Symbol(setup, Decl(inferenceExactOptionalProperties2.ts, 41, 5)) + + TActors extends Record = {}, +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 43, 23)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>UnknownActorLogic : Symbol(UnknownActorLogic, Decl(inferenceExactOptionalProperties2.ts, 8, 1)) + +>(implementations?: { +>implementations : Symbol(implementations, Decl(inferenceExactOptionalProperties2.ts, 45, 2)) + + actors?: { [K in keyof TActors]: TActors[K] }; +>actors : Symbol(actors, Decl(inferenceExactOptionalProperties2.ts, 45, 21)) +>K : Symbol(K, Decl(inferenceExactOptionalProperties2.ts, 46, 14)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 43, 23)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 43, 23)) +>K : Symbol(K, Decl(inferenceExactOptionalProperties2.ts, 46, 14)) + +}): { + createMachine: < +>createMachine : Symbol(createMachine, Decl(inferenceExactOptionalProperties2.ts, 47, 5)) + + const TConfig extends MachineConfig>, +>TConfig : Symbol(TConfig, Decl(inferenceExactOptionalProperties2.ts, 48, 18)) +>MachineConfig : Symbol(MachineConfig, Decl(inferenceExactOptionalProperties2.ts, 25, 1)) +>ToProvidedActor : Symbol(ToProvidedActor, Decl(inferenceExactOptionalProperties2.ts, 33, 24)) +>TActors : Symbol(TActors, Decl(inferenceExactOptionalProperties2.ts, 43, 23)) + + >( + config: TConfig, +>config : Symbol(config, Decl(inferenceExactOptionalProperties2.ts, 50, 4)) +>TConfig : Symbol(TConfig, Decl(inferenceExactOptionalProperties2.ts, 48, 18)) + + ) => void; +}; + +declare const counterLogic: ActorLogic<{ type: "INCREMENT" }>; +>counterLogic : Symbol(counterLogic, Decl(inferenceExactOptionalProperties2.ts, 55, 13)) +>ActorLogic : Symbol(ActorLogic, Decl(inferenceExactOptionalProperties2.ts, 4, 2)) +>type : Symbol(type, Decl(inferenceExactOptionalProperties2.ts, 55, 40)) + +// example usage +setup({ +>setup({ actors: { counter: counterLogic },}).createMachine : Symbol(createMachine, Decl(inferenceExactOptionalProperties2.ts, 47, 5)) +>setup : Symbol(setup, Decl(inferenceExactOptionalProperties2.ts, 41, 5)) + + actors: { counter: counterLogic }, +>actors : Symbol(actors, Decl(inferenceExactOptionalProperties2.ts, 58, 7)) +>counter : Symbol(counter, Decl(inferenceExactOptionalProperties2.ts, 59, 11)) +>counterLogic : Symbol(counterLogic, Decl(inferenceExactOptionalProperties2.ts, 55, 13)) + +}).createMachine({ +>createMachine : Symbol(createMachine, Decl(inferenceExactOptionalProperties2.ts, 47, 5)) + + entry: assign((spawn) => { +>entry : Symbol(entry, Decl(inferenceExactOptionalProperties2.ts, 60, 18)) +>assign : Symbol(assign, Decl(inferenceExactOptionalProperties2.ts, 29, 1)) +>spawn : Symbol(spawn, Decl(inferenceExactOptionalProperties2.ts, 61, 17)) + + spawn("counter"); // ok +>spawn : Symbol(spawn, Decl(inferenceExactOptionalProperties2.ts, 61, 17)) + + spawn("alarm"); // error +>spawn : Symbol(spawn, Decl(inferenceExactOptionalProperties2.ts, 61, 17)) + + return {}; + }), +}); + +// no provided actors, `assign` should still work +setup().createMachine({ +>setup().createMachine : Symbol(createMachine, Decl(inferenceExactOptionalProperties2.ts, 47, 5)) +>setup : Symbol(setup, Decl(inferenceExactOptionalProperties2.ts, 41, 5)) +>createMachine : Symbol(createMachine, Decl(inferenceExactOptionalProperties2.ts, 47, 5)) + + entry: assign(() => ({})), +>entry : Symbol(entry, Decl(inferenceExactOptionalProperties2.ts, 69, 23)) +>assign : Symbol(assign, Decl(inferenceExactOptionalProperties2.ts, 29, 1)) + +}); + diff --git a/tests/baselines/reference/inferenceExactOptionalProperties2.types b/tests/baselines/reference/inferenceExactOptionalProperties2.types new file mode 100644 index 00000000000..964dd94f5b3 --- /dev/null +++ b/tests/baselines/reference/inferenceExactOptionalProperties2.types @@ -0,0 +1,158 @@ +//// [tests/cases/compiler/inferenceExactOptionalProperties2.ts] //// + +=== inferenceExactOptionalProperties2.ts === +type Values = T[keyof T]; +>Values : Values + +type EventObject = { +>EventObject : { type: string; } + + type: string; +>type : string + +}; + +interface ActorLogic { + transition: (ev: TEvent) => unknown; +>transition : (ev: TEvent) => unknown +>ev : TEvent +} + +type UnknownActorLogic = ActorLogic; +>UnknownActorLogic : ActorLogic + +interface ProvidedActor { + src: string; +>src : string + + logic: UnknownActorLogic; +>logic : UnknownActorLogic +} + +interface ActionFunction { + (): void; + _out_TActor?: TActor; +>_out_TActor : TActor | undefined +} + +interface AssignAction { + (): void; + _out_TActor?: TActor; +>_out_TActor : TActor | undefined +} + +interface MachineConfig { + entry?: ActionFunction; +>entry : ActionFunction | undefined +} + +declare function assign( +>assign : (_: (spawn: (actor: TActor["src"]) => void) => {}) => AssignAction + + _: (spawn: (actor: TActor["src"]) => void) => {}, +>_ : (spawn: (actor: TActor["src"]) => void) => {} +>spawn : (actor: TActor["src"]) => void +>actor : TActor["src"] + +): AssignAction; + +type ToProvidedActor> = +>ToProvidedActor : ToProvidedActor + + Values<{ + [K in keyof TActors & string]: { + src: K; +>src : K + + logic: TActors[K]; +>logic : TActors[K] + + }; + }>; + +declare function setup< +>setup : = {}>(implementations?: { actors?: { [K in keyof TActors]: TActors[K]; }; } | undefined) => { createMachine: >>(config: TConfig) => void; } + + TActors extends Record = {}, +>(implementations?: { +>implementations : { actors?: { [K in keyof TActors]: TActors[K]; }; } | undefined + + actors?: { [K in keyof TActors]: TActors[K] }; +>actors : { [K in keyof TActors]: TActors[K]; } | undefined + +}): { + createMachine: < +>createMachine : >>(config: TConfig) => void + + const TConfig extends MachineConfig>, + >( + config: TConfig, +>config : TConfig + + ) => void; +}; + +declare const counterLogic: ActorLogic<{ type: "INCREMENT" }>; +>counterLogic : ActorLogic<{ type: "INCREMENT"; }> +>type : "INCREMENT" + +// example usage +setup({ +>setup({ actors: { counter: counterLogic },}).createMachine({ entry: assign((spawn) => { spawn("counter"); // ok spawn("alarm"); // error return {}; }),}) : void +>setup({ actors: { counter: counterLogic },}).createMachine : ; }>>(config: TConfig) => void +>setup({ actors: { counter: counterLogic },}) : { createMachine: ; }>>(config: TConfig) => void; } +>setup : = {}>(implementations?: { actors?: { [K in keyof TActors]: TActors[K]; }; } | undefined) => { createMachine: >>(config: TConfig) => void; } +>{ actors: { counter: counterLogic },} : { actors: { counter: ActorLogic<{ type: "INCREMENT"; }>; }; } + + actors: { counter: counterLogic }, +>actors : { counter: ActorLogic<{ type: "INCREMENT"; }>; } +>{ counter: counterLogic } : { counter: ActorLogic<{ type: "INCREMENT"; }>; } +>counter : ActorLogic<{ type: "INCREMENT"; }> +>counterLogic : ActorLogic<{ type: "INCREMENT"; }> + +}).createMachine({ +>createMachine : ; }>>(config: TConfig) => void +>{ entry: assign((spawn) => { spawn("counter"); // ok spawn("alarm"); // error return {}; }),} : { entry: AssignAction<{ src: "counter"; logic: ActorLogic<{ type: "INCREMENT"; }>; }>; } + + entry: assign((spawn) => { +>entry : AssignAction<{ src: "counter"; logic: ActorLogic<{ type: "INCREMENT"; }>; }> +>assign((spawn) => { spawn("counter"); // ok spawn("alarm"); // error return {}; }) : AssignAction<{ src: "counter"; logic: ActorLogic<{ type: "INCREMENT"; }>; }> +>assign : (_: (spawn: (actor: TActor["src"]) => void) => {}) => AssignAction +>(spawn) => { spawn("counter"); // ok spawn("alarm"); // error return {}; } : (spawn: (actor: "counter") => void) => {} +>spawn : (actor: "counter") => void + + spawn("counter"); // ok +>spawn("counter") : void +>spawn : (actor: "counter") => void +>"counter" : "counter" + + spawn("alarm"); // error +>spawn("alarm") : void +>spawn : (actor: "counter") => void +>"alarm" : "alarm" + + return {}; +>{} : {} + + }), +}); + +// no provided actors, `assign` should still work +setup().createMachine({ +>setup().createMachine({ entry: assign(() => ({})),}) : void +>setup().createMachine : >(config: TConfig) => void +>setup() : { createMachine: >(config: TConfig) => void; } +>setup : = {}>(implementations?: { actors?: { [K in keyof TActors]: TActors[K]; }; } | undefined) => { createMachine: >>(config: TConfig) => void; } +>createMachine : >(config: TConfig) => void +>{ entry: assign(() => ({})),} : { entry: AssignAction; } + + entry: assign(() => ({})), +>entry : AssignAction +>assign(() => ({})) : AssignAction +>assign : (_: (spawn: (actor: TActor["src"]) => void) => {}) => AssignAction +>() => ({}) : () => {} +>({}) : {} +>{} : {} + +}); + diff --git a/tests/cases/compiler/inferenceExactOptionalProperties1.ts b/tests/cases/compiler/inferenceExactOptionalProperties1.ts new file mode 100644 index 00000000000..2cead6eccae --- /dev/null +++ b/tests/cases/compiler/inferenceExactOptionalProperties1.ts @@ -0,0 +1,5 @@ +// @strict: true +// @exactOptionalPropertyTypes: true +// @noEmit: true + +type Test1 = { prop?: never } extends { prop?: infer T } ? T : false; // never diff --git a/tests/cases/compiler/inferenceExactOptionalProperties2.ts b/tests/cases/compiler/inferenceExactOptionalProperties2.ts new file mode 100644 index 00000000000..74802293bd8 --- /dev/null +++ b/tests/cases/compiler/inferenceExactOptionalProperties2.ts @@ -0,0 +1,76 @@ +// @strict: true +// @exactOptionalPropertyTypes: true +// @noEmit: true + +type Values = T[keyof T]; + +type EventObject = { + type: string; +}; + +interface ActorLogic { + transition: (ev: TEvent) => unknown; +} + +type UnknownActorLogic = ActorLogic; + +interface ProvidedActor { + src: string; + logic: UnknownActorLogic; +} + +interface ActionFunction { + (): void; + _out_TActor?: TActor; +} + +interface AssignAction { + (): void; + _out_TActor?: TActor; +} + +interface MachineConfig { + entry?: ActionFunction; +} + +declare function assign( + _: (spawn: (actor: TActor["src"]) => void) => {}, +): AssignAction; + +type ToProvidedActor> = + Values<{ + [K in keyof TActors & string]: { + src: K; + logic: TActors[K]; + }; + }>; + +declare function setup< + TActors extends Record = {}, +>(implementations?: { + actors?: { [K in keyof TActors]: TActors[K] }; +}): { + createMachine: < + const TConfig extends MachineConfig>, + >( + config: TConfig, + ) => void; +}; + +declare const counterLogic: ActorLogic<{ type: "INCREMENT" }>; + +// example usage +setup({ + actors: { counter: counterLogic }, +}).createMachine({ + entry: assign((spawn) => { + spawn("counter"); // ok + spawn("alarm"); // error + return {}; + }), +}); + +// no provided actors, `assign` should still work +setup().createMachine({ + entry: assign(() => ({})), +});