Open
Description
Bug Report
π Search Terms
contextual, template literal, key remapping, object property
π Version & Regression Information
- This is the behavior in every version I tried
β― Playground Link
Playground link with relevant code
π» Code
interface MachineConfig<TEvent extends { type: string }> {
schema?: {
events?: TEvent;
};
on?: {
[K in TEvent["type"] as `on${K}`]?: (
ev: TEvent extends { type: K } ? TEvent : never
) => void;
};
}
declare function createMachine<TEvent extends { type: string }>(
config: MachineConfig<TEvent>
): void;
export default createMachine({
schema: {
events: {} as { type: "FOO" },
},
on: {
onFOO: (ev) => {
ev.type; // should be `FOO`, but `ev` is an implicit `any`
},
},
});
π Actual behavior
Implicit any is reported
π Expected behavior
ev
should get inferred as { type: 'FOO' }
getTypeOfPropertyOfContextualType
explicitly~ ignores this case:
if (isGenericMappedType(t) && !t.declaration.nameType) {
const constraint = getConstraintTypeFromMappedType(t);
const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint;
const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name));
if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) {
return substituteIndexedMappedType(t, propertyNameType);
}
}
Note that nameType
comes from an argument provided by this call within getContextualTypeForObjectLiteralElement
but it's undefined
:
getTypeOfPropertyOfContextualType(type, symbol.escapedName, getSymbolLinks(symbol).nameType);
I guess the fix here would be to not ignore this potential substitution based on !t.declaration.nameType
and construct the possible K
constraint based on the t.declaration.nameType
and name
. I don't know how to do this in a sufficiently generic manner though.