Skip to content

Contextual type of a property type not inferred with key remappingΒ #48855

Open
@Andarist

Description

@Andarist

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 nameTypecomes 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions