Description
Bug Report
π Search Terms
inference conditional function parameters contextual optional property
π Version & Regression Information
This is the behavior present in all 4.x versions available on the playground, including 4.5-beta.
β― Playground Link
Playground resembling a real-life use case
π» Code
export interface TypegenDisabled { "@@xstate/typegen": false; }
export interface TypegenEnabled { "@@xstate/typegen": true; }
type ActionFunction<TEvent extends { type: string }> = (event: TEvent) => void;
// this is supposed to "route" the second argument based on the information provided within the first one
declare function createMachine<
TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled
>(
config: {
types?: TTypesMeta;
},
implementations: TTypesMeta extends TypegenEnabled
? ActionFunction<{ type: "test" }>
: ActionFunction<{ type: string }>
): void;
// it doesn't work with inference, this doesn't contain explicit type param and the optional `types` property ain't used explicitly
createMachine({
// if we uncomment this property it starts to work
// types: {} as TypegenDisabled
}, (ev) => {
// `ev` is implicitly typed as `any`
ev.type;
// @ts-expect-error (it doesn't error since `ev` is `any`)
ev.unknown;
// @ts-expect-error (it doesn't error since `ev` is `any`)
((_type: "test") => null)(ev.type);
});
π Actual behavior
The inferred type of this function is basically "AnyFunction
" because the inference hits assignNonContextualParameterTypes
and not explicit type params are given here.
From what I've seen in the debugger (when debugging the code from which this minimal repro has been created) the contextualSignature
for this gets computed as undefined
. This happens because the conditional type is "converted" to a union and the functions in the resulting union have no sufficient overlap (they are failing compareSignaturesIdentical
check).
However, this feels like a piece of information about what happens "later on" and how the implicit any has been computed here. The issue I'm reporting is that this conditional type cannot be resolved "soon enough" for the correct branch from it to be chosen before we get to computing the contextualSignature
here.
π Expected behavior
I would expect TTypesMeta
to be inferred as TypegenDisabled
regardless of the types
property in the second argument being in the object explicitly or not. Since it's an optional property its type should be inferred here as the default given in the generic signature.