<!DOCTYPE html>
<html ng-app="app">

  <head>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <h1>Angularjs controller as via typescript invoke controller function from directive</h1>
    <div ng-controller="MainController as vm">
      <button ng-click="vm.sayHello('Hello John')">Hallo John from the Main Controller</button>
      <test-directive test-fn="vm.sayHello"></test-directive>
    </div>
    
    <script src="//code.angularjs.org/1.5.8/angular.js"></script>
    <script src="app.js"></script>
    <script src="controllers.js"></script>
    <script src="services.js"></script>
    <script src="directives.js"></script>
    <script data-require="typescript@*" data-semver="1.7.3" src="https://code.angularjs.org/tools/typescript.js"></script>
  </body>

</html>
/* Styles go here */

module Plunker {
  angular.module("app", []);
}
module Plunker {
    "use strict"

    export interface IMainScope {
        sayHello(message:string): void;
    }
    
    class MainController implements IMainScope {

        static $inject = ["LogService"];

        constructor(private logService:ILogService) { }
        
        sayHello(message:string) {
          console.log("MainController sayHello", message);
          // Cannot read property 'logService' of undefined if gets call from directive
          this.logService.log(message);
        }
    }

    angular.module("app").controller("MainController", MainController);
}
module Plunker {
    "use strict"

    export interface ILogService {
        log(message:string): void;
    }

    class LogService implements ILogService {
        static $inject = ["$window"];

        constructor(private $window: any) { 
          
        }
        
        log(message:string) {
          this.$window.alert(`LogService :: ${message}`);
        }
    }

    angular.module("app").service("LogService", LogService);
}
module Plunker {
    "use strict";

    interface TestDirectiveScope extends ng.IScope {
        hello():void;
        firstName:string;
        testFn(message:string):void
    }

    class TestDirective implements ng.IDirective {
        public restrict = "E";
        public templateUrl = "test-directive.html";
        public replace = true;
        public scope:any = {
            testFn: "&"
        };

        constructor() { }

        public link:ng.IDirectiveLinkFn = (scope:TestDirectiveScope, element:ng.IAugmentedJQuery, attrs:ng.IAttributes):void => {
            scope.hello = () => {
              console.log("TestDirective", scope.firstName);
              scope.testFn()(scope.firstName);
            };
        }

        static factory():ng.IDirectiveFactory {
            let directive:ng.IDirectiveFactory = () => new TestDirective();
            return directive;
        }
    }

    angular.module("app").directive("testDirective", TestDirective.factory());
}
<div>
  <hr/ >
  <h3>Try to call the MainController sayHello function directives</h3>
  First name: <input ng-model="firstName" />
  <button ng-click="hello()">Say Hello to {{firstName}}</button>
  <hr />
</div>