4.23 Contextually Typed Expressions

Type checking of an expression is improved in several contexts by factoring in the type of the destination of the value computed by the expression. In such situations, the expression is said to be contextually typed by the type of the destination. An expression is contextually typed in the following circumstances:

  • In a variable, parameter, binding property, binding element, or member declaration, an initializer expression is contextually typed by
    • the type given in the declaration’s type annotation, if any, or otherwise
    • for a parameter, the type provided by a contextual signature (section 4.10), if any, or otherwise
    • the type implied by the binding pattern in the declaration (section 5.2.3), if any.
  • In the body of a function declaration, function expression, arrow function, method declaration, or get accessor declaration that has a return type annotation, return expressions are contextually typed by the type given in the return type annotation.
  • In the body of a function expression or arrow function that has no return type annotation, if the function expression or arrow function is contextually typed by a function type with exactly one call signature, and if that call signature is non-generic, return expressions are contextually typed by the return type of that call signature.
  • In the body of a constructor declaration, return expressions are contextually typed by the containing class type.
  • In the body of a get accessor with no return type annotation, if a matching set accessor exists and that set accessor has a parameter type annotation, return expressions are contextually typed by the type given in the set accessor’s parameter type annotation.
  • In a typed function call, argument expressions are contextually typed by their corresponding parameter types.
  • In a contextually typed object literal, each property value expression is contextually typed by
    • the type of the property with a matching name in the contextual type, if any, or otherwise
    • for a numerically named property, the numeric index type of the contextual type, if any, or otherwise
    • the string index type of the contextual type, if any.
  • In a contextually typed array literal expression containing no spread elements, an element expression at index N is contextually typed by
    • the type of the property with the numeric name N in the contextual type, if any, or otherwise
    • the numeric index type of the contextual type, if any.
  • In a contextually typed array literal expression containing one or more spread elements, an element expression at index N is contextually typed by the numeric index type of the contextual type, if any.
  • In a contextually typed parenthesized expression, the contained expression is contextually typed by the same type.
  • In a type assertion, the expression is contextually typed by the indicated type.
  • In a || operator expression, if the expression is contextually typed, the operands are contextually typed by the same type. Otherwise, the right expression is contextually typed by the type of the left expression.
  • In a contextually typed conditional operator expression, the operands are contextually typed by the same type.
  • In an assignment expression, the right hand expression is contextually typed by the type of the left hand expression.

In the following example

  1. interface EventObject {
  2. x: number;
  3. y: number;
  4. }
  5. interface EventHandlers {
  6. mousedown?: (event: EventObject) => void;
  7. mouseup?: (event: EventObject) => void;
  8. mousemove?: (event: EventObject) => void;
  9. }
  10. function setEventHandlers(handlers: EventHandlers) { ... }
  11. setEventHandlers({
  12. mousedown: e => { startTracking(e.x, e.y); },
  13. mouseup: e => { endTracking(); }
  14. });

the object literal passed to ‘setEventHandlers’ is contextually typed to the ‘EventHandlers’ type. This causes the two property assignments to be contextually typed to the unnamed function type ‘(event: EventObject) => void’, which in turn causes the ‘e’ parameters in the arrow function expressions to automatically be typed as ‘EventObject’.