-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Open
Labels
Needs InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
Milestone
Description
Bug Report
🔎 Search Terms
concrete object, assignable, generic mapped type, concrete constraint, partially
🕗 Version & Regression Information
- This is the behavior in every version I tried (interestingly though the intersected variant of this target type, presented in the playground, became valid in TS 3.6)
⏯ Playground Link
Playground link with relevant code
💻 Code
type ExtractEvent<
TEvent extends { type: string },
TEventType extends TEvent["type"]
> = TEvent extends {
type: TEventType;
}
? TEvent
: never;
type TransitionConfig<TContext, TEvent extends { type: string }> = {
actions?: {
type: string;
};
};
type IntersectedTransitionConfigMap<TContext, TEvent extends { type: string }> = {
[K in TEvent["type"]]?: TransitionConfig<TContext, ExtractEvent<TEvent, K>>;
} & {
"*": TransitionConfig<TContext, TEvent>;
};
type TransitionConfigMap<TContext, TEvent extends { type: string }> = {
[K in TEvent["type"] | "*"]?: K extends "*"
? TransitionConfig<TContext, TEvent>
: TransitionConfig<TContext, ExtractEvent<TEvent, K>>;
};
export function genericFn<TEvent extends { type: string }>() {
const wildcardTransitionConfig = {
"*": { actions: { type: "someAction" } },
} as const;
// this should be assignable, in the same way as the following assignment is OK
let test: TransitionConfigMap<
{ counter: number },
{ type: TEvent["type"] }
> = {} as typeof wildcardTransitionConfig;
// concrete prop is assignable to the concrete prop of this mapped type
test["*"] = {} as typeof wildcardTransitionConfig["*"];
// similar intersected type accepts this concrete object
let test2: IntersectedTransitionConfigMap<
{ counter: number },
{ type: TEvent["type"] }
> = {} as typeof wildcardTransitionConfig;
}
🙁 Actual behavior
The concrete object is not assignable to this generic mapped with a partially concrete constraint
🙂 Expected behavior
This should be allowed, or the second assignment (the one to test['*']
) should also be considered as invalid.
The problem originates here where this relation check fails:
indexedAccessType // { readonly "*": { readonly actions: { readonly type: "someAction"; }; }; }[(("*" | TEvent["type"]) & "*") & K]
templateType // (K extends "*" ? TransitionConfig<{ counter: number; }, { type: TEvent["type"]; }> : TransitionConfig<{ counter: number; }, ExtractEvent<{ type: TEvent["type"]; }, K>>) | undefined
isRelatedTo(indexedAccessType, templateType, RecursionFlags.Both, reportErrors) // 0
Which leads us to checking if a type is assignable to a conditional type and that is rarely even possible, as only limited scenarios are even checked for such a case (here)
Metadata
Metadata
Assignees
Labels
Needs InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.