# AUR0107

## Error Message

`AUR0107: Ast eval error: expression is not a function.`

## Description

This error occurs during the evaluation of a binding expression when an attempt is made to invoke an expression using call syntax (`()`), but the expression itself evaluates to a value that is not a function type (e.g., it evaluates to a string, number, object, null, or undefined).

This is similar to AUR0111 (`ast_name_is_not_a_function`), but typically occurs when the part being called is itself a computed expression rather than a direct variable or property name.

## Cause

The fundamental cause is trying to execute something that isn't executable. This often happens when:

1. **Incorrect Return Type:** An inner expression (e.g., a function call, a property access) returns a non-function value, which is then immediately invoked. Example: `getHandler()()` where `getHandler()` returns a string instead of a function.
2. **Array/Object Access:** Attempting to call an element retrieved from an array or object that isn't a function. Example: `actions[type]()` where `actions[type]` resolves to `null` or a non-function value.
3. **Typo/Logic Error:** A simple mistake in the expression logic leads to a non-function value being in the position where a function is expected for invocation.

## Solution

1. **Verify Expression Result:** Ensure that the expression preceding the `()` evaluates to a function at runtime. Use `console.log` or debugging tools to inspect the value and its type just before the call attempt.
2. **Check Function Returns:** If the expression involves a function call (like `getHandler()()`), verify that the inner function (`getHandler`) correctly returns another function under all conditions.
3. **Check Array/Object Contents:** If accessing an array element or object property before calling (like `actions[type]()`), ensure the value stored at that index/key is indeed a function. Provide defaults or add checks if necessary.
4. **Correct Logic:** Review the binding expression for any logical errors or typos.

## Example

```html
<!-- Assume 'getAction' is supposed to return a function based on 'status' -->
<!-- Assume 'callbacks' is an object where values should be functions -->

<!-- Incorrect: 'getAction(status)' might return null or a string -->
<button click.trigger="getAction(status)()">Perform Action</button>

<!-- Incorrect: 'callbacks[key]' might not exist or not be a function -->
<div mousemove.trigger="callbacks[key]()">Handle Callback</div>

<!-- Correct: Ensure the expression results in a function before calling -->
<!-- (Correction often needs to happen in the view model logic) -->
<button click.trigger="performAction()">Perform Action</button> <!-- VM handles lookup -->

```

```typescript
// View Model Example
import { customElement } from 'aurelia';

@customElement({ /* ... */ })
export class MyComponent {
  status = 'pending';
  key = 'onMove';

  callbacks: Record<string, (() => void) | null> = {
    onMove: () => console.log('Moved!'),
    onEnter: null // Example non-function
  };

  getAction(currentStatus: string): (() => void) | null {
    if (currentStatus === 'pending') {
      return () => console.log('Processing pending action...');
    } else if (currentStatus === 'complete') {
      // Incorrectly returning a string instead of a function could cause AUR0107
      // return 'Action Complete';
      return () => console.log('Action Complete');
    }
    return null; // Returning null would also cause AUR0107 if called
  }

  // Safer approach for the template
  performAction() {
    const action = this.getAction(this.status);
    if (typeof action === 'function') {
      action();
    } else {
      console.warn('No action available for status:', this.status);
    }
  }

  // Safer approach for callbacks
  handleCallback(callbackKey: string) {
     const callback = this.callbacks[callbackKey];
     if(typeof callback === 'function') {
       callback();
     }
  }
  // In template: <div mousemove.trigger="handleCallback(key)">Handle Callback</div>
}
```

## Debugging Tips

* Isolate the complex expression being called in the template.
* Use `console.log` or breakpoints in the view model to evaluate the parts of the expression and determine what the non-function value is and why it's occurring.
* Refactor complex call logic into view model methods for better clarity and easier debugging, performing necessary type checks within the method before invocation.
