Add field on Case type form
If you're ok with it not being tightly integrated (i.e. automatically available in the xml or to the api), then you can do something like below, which adds a field labelled "Boo" to the case type edit screen.

Thanks for asking this question. It's probably helped me more than you, since it's helped clarify for me how this all works. And it occurs to me that customizing an existing form is probably a much more likely task for developers than writing your own angular form from scratch, which is what all the tutorials show.

function myextension_civicrm_alterAngular(\Civi\Angular\Manager $angular) {
  $changeSet = \Civi\Angular\ChangeSet::create('add_casetype_custom_field')
    -&gt;alterHtml('~/crmCaseType/caseTypeDetails.html',
      function (phpQueryObject $doc) {
        $doc-&gt;find('div.crm-group')-&gt;append('
          &lt;fieldset class="crm-collapsible"&gt;
            &lt;legend class="collapsible-title"&gt;{{ ts(\'My Custom Fields\') }}&lt;/legend&gt;
            &lt;div ng-controller="CustomFieldCtrl"&gt;
              &lt;div crm-ui-field="{name: \'mycustomfield\', title: ts(\'Boo\')}"&gt;
                &lt;input crm-ui-id="mycustomfield" class="crm-form-text" name="mycustomfield" ng-model="mymodel.cusfield"&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/fieldset&gt;
        ');
      });
  $angular-&gt;add($changeSet);

  CRM_Core_Resources::singleton()-&gt;addScriptFile('my.extension.name', 'js/angCustomField.js');
}


Reference: https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/

And here is the contents of js/angCustomField.js:

(function(angular, $) {
  var crmCaseType = angular.module('crmCaseType');
  crmCaseType.controller('CustomFieldCtrl', function($scope) {
    // Need to replace this with an ajax call right here to look up the value from the db.
    $scope.mymodel = { cusfield: 'value looked up from db' };

    // just show that this is executing and we have the right id
    console.log($scope.caseType.id);

    // alias the real save() function so that we can do our stuff too
    var proxiedSave = $scope.$parent.$parent.save;
    $scope.$parent.$parent.save = function() {
      console.log($scope.caseType.id);
      console.log($scope.mymodel.cusfield);

      //
      // Do ajax api or whatever here to save the value to db
      //
      // IMPORTANT: Always validate the input server-side before using it even if you have javascript validation client-side since that can be easily bypassed. This isn't specific to angular it just seems to be ignored in all the angular tutorials. Even a plain html form with e.g. a select list can still submit values not in the select list - always need to validate server-side.

      // Now call the original save
      return proxiedSave.apply(this);
    }
  });
})(angular, CRM.$);


Some notes:


Note we're adding our own nested child controller in the line that has ng-controller="CustomFieldCtrl". This matches up to the controller in our js file.
The ng-model="mymodel.cusfield" value HAS TO HAVE A DOT IN IT. It just doesn't work if it doesn't. This matches up to the $scope.mymodel = ... line in our js file.