2013-03-21 9 views
4

Я использую Breeze + Typcript + Knockout для Spa, и перед этим сталкиваюсь со следующей проблемой: , когда я создаю новый объект с EntityManager.createEntity, машинопись не позволяет использовать наблюдаемые что Бриз генерируется из метаданных. Typcript «видит» только свойства «entityAspect» и «entityType». Я использую определения типов DefinitelyTyped. Любая помощь очень ценится!Breeze entity с машинописными текстами

ответ

1

Глядя на: https://github.com/borisyankov/DefinitelyTyped/blob/master/knockout/knockout.d.ts

функций, которые вы видите на кё (например, наблюдаемым и т.д.) являются функции, определенные на KnockoutStatic интерфейс из-за этой линии:

declare var ko: KnockoutStatic; 

Вот фрагмент этого интерфейса:

interface KnockoutStatic { 
    utils: KnockoutUtils; 
    memoization: KnockoutMemoization; 
    bindingHandlers: KnockoutBindingHandlers; 
    virtualElements: KnockoutVirtualElements; 
    extenders: KnockoutExtenders; 

    applyBindings(viewModel: any, rootNode?: any): void; 
    applyBindingsToDescendants(viewModel: any, rootNode: any): void; 
    applyBindingsToNode(node: Element, options: any, viewModel: any): void; 

    subscribable: KnockoutSubscribableStatic; 
    observable: KnockoutObservableStatic; 
    computed: KnockoutComputedStatic; 
    observableArray: KnockoutObservableArrayStatic; 
    ..... 

Итак, если вам нужны новые функции на ko, вам необходимо определить новые функции для интерфейса KnockoutStatic, например:

interface KnockoutStatic { 
    yourFunc: KnockoutObservableStatic; 
} 

и т. Д. Поскольку интерфейсы открыты, вы можете объявить различные части определения интерфейса в нескольких файлах. Надеюсь это поможет.

+0

Hy, спасибо за Ваш ответ. Я не уверен, что это решит мою проблему, которая является TypeScript неспособным поймать динамическую природу Breeze Entities. – frenchfaso

5

Вы можете создать интерфейс для вашего типа, который простирается breeze.Entity:

/// <reference path="breeze.d.ts" /> 
module model { 
    export interface ResponsesItem extends breeze.Entity { 
     ContentTypeID: string; 
     Title: string; 
     Description: string; 
     EventDate: any; 
     /* etc. */ 
    } 
} 

Вы можете бросить свои объекты к этому интерфейсу всякий раз, когда вам нужно работать с ними в типизированной образом, например, в результате запрос при загрузке с сервера:

 private loadResponses(): void { 
     this.dataservice.ListResponses() 
      .then((data: { results: breeze.Entity[]; query: breeze.EntityQuery; XHR: XMLHttpRequest; }) => { 
       var results: model.ResponsesItem[] = <model.ResponsesItem[]>data.results; 
       // Do something with typed results array here. 
     }).fail((error) => { 
      this.handleDataError(error); 
     }); 
     } 
+0

Спасибо JcFx, звучит хорошо! Попробуй это и отчитайся :-) PS: Что делать, если у меня есть несколько моделей, отправленных разными запросами Breeze? – frenchfaso

+0

Несколько интерфейсов? – frenchfaso

+0

Я не совсем уверен, что вы просите, но да. У меня есть отдельный метод для моего клиентского пакета данных для каждого типа, поэтому я знаю, чего я ожидаю от конкретного вызова, и могу использовать его соответствующим образом. Имейте в виду, что свойство интерфейса может быть другим интерфейсом, поэтому вы можете иметь структурированную, типизированную модель. Также ознакомьтесь с полезным шаблоном T4 от Christoffer для создания интерфейсов со своих серверных классов: https://github.com/cskeppstedt/t4ts – JcFx

2

Проверьте мой ответ на Breeze.js typed entities, где я взломал T4TS выплюнуть TS определения, которые поддерживают Breeze.

0

Ниже приведена страница, которую вы можете добавить на свой сайт, чтобы создавать определения интерфейсов типов. Страница извлекает метаданные бриза, а затем выполняет итерацию по всем типам и выводит декларацию интерфейса типов для каждого типа. Результат этой страницы можно вставить в любой файл машинописного файла (* .ts) или файл описания машинописных файлов (* .d.ts). Примените результаты в объявлении модуля, если вы хотите, чтобы пространство импортозаместимых интерфейсов: declare module northwind { ... paste interfaces here... }.

Прежде чем использовать эту страницу, вам нужно будет сделать одно изменение: измените URL-адрес контроллера сущности менеджера «api/northwind» на любой URL-адрес вашего контроллера.

сгенерированных интерфейсы имеет зависимость от определений машинописи Knockout.js, которые вы можете захватить здесь: https://github.com/borisyankov/DefinitelyTyped/tree/master/knockout/

Использование Northwind примера из learn.breezejs.com, выхода этой страницы генератора определения будет что-то вроде этого:

export interface Employee extends breeze.Entity { 
    FirstName: KnockoutObservable<string>; 
    LastName: KnockoutObservable<string>; 
} 

вы могли бы выполнить запрос, используя ветер и привести результаты в массив сотрудников, как это:

var manager = new breeze.EntityManager('api/northwind'); 

var query = new breeze.EntityQuery() 
    .from("Employees"); 

manager.executeQuery(query).then(data => { 
    // ***cast the results to a strongly typed array of Employee*** 
    var employees = <Employee[]>data.results; 
}).fail(e => { 
    alert(e); 
}); 

ниже - страница генераторов определений - добавьте новый html-файл в проект под названием «определения.html», запустите проект и перейдите на страницу.

<html> 
<head> 
    <title>Typescript Definition Generator</title> 
    <style> 
     code { 
      white-space: pre; 
     } 
    </style> 
    <script src="//code.jquery.com/jquery-2.1.0.min.js"></script> 
    <script src="//ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script> 
    <script src="//cdnjs.cloudflare.com/ajax/libs/q.js/1.0.0/q.min.js"></script> 
    <script src="//cdnjs.cloudflare.com/ajax/libs/breezejs/1.4.4/breeze.min.js"></script> 
    <script type="text/javascript"> 
     $(document).ready(function() { 
      var entityManager = new breeze.EntityManager('api/northwind'); 
      entityManager.fetchMetadata() 
       .then(function() { 
        var html = '', 
         types = entityManager.metadataStore.getEntityTypes(), 
         type, 
         i, 
         j, 
         property, 
         crlf = String.fromCharCode(13), 
         code = document.createElement('code'), 
         script = document.createElement('script'); 

        function getJSType(metadataType) { 
         if (/(Int64)|(Int32)|(Int16)|(Byte)|(Decimal)|(Double)|(Single)|(number)/.test(metadataType)) 
          return 'number'; 
         else if (/(DateTime)|(DateTimeOffset)|(Time)|(Date)/.test(metadataType)) 
          return 'Date'; 
         else if (/(Boolean)/i.test(metadataType)) 
          return 'boolean'; 
         return 'string'; 
        } 

        for (i = 0; i < types.length; i++) { 
         // type declaration 
         var type = types[i]; 
         html += 'export interface ' + type.shortName; 

         // base type 
         html += ' extends '; 
         if (type.hasOwnProperty('baseEntityType')) { 
          html += type.baseEntityType.shortName; 
         } else { 
          html += 'breeze.Entity'; 
         } 
         html += ' {' + crlf; 

         // data properties 
         for (j = 0; j < type.dataProperties.length; j++) { 
          property = type.dataProperties[j]; 
          if (type.baseEntityType && type.baseEntityType.dataProperties.filter(function (p) { return p.name === property.name; }).length > 0) 
           continue; 
          html += ' ' + property.name; 
          //if (property.isNullable) 
          // html += '?'; 
          html += ': KnockoutObservable&lt;'; 
          html += getJSType(property.dataType.name); 
          html += '&gt;; //' + property.dataType.name + crlf; 
         } 

         // navigation properties 
         for (j = 0; j < type.navigationProperties.length; j++) { 
          property = type.navigationProperties[j]; 
          if (type.baseEntityType && type.baseEntityType.navigationProperties.filter(function (p) { return p.name === property.name; }).length > 0) 
           continue; 
          html += ' ' + property.name; 
          //if (property.isNullable) 
          // html += '?'; 
          if (property.isScalar) 
           html += ': KnockoutObservable&lt;'; 
          else 
           html += ': KnockoutObservableArray&lt;'; 
          html += property.entityType.shortName; 
          html += '&gt;;' + crlf; 
         } 

         html += '}' + crlf + crlf; 
        } 

        code.innerHTML = html; 

        $(code).addClass('prettyprint'); 

        document.body.appendChild(code); 

        script.setAttribute('src', '//google-code-prettify.googlecode.com/svn/loader/run_prettify.js'); 
        document.body.appendChild(script); 
       }) 
       .fail(function (reason) { 
        alert(reason); 
       }); 
     }); 
    </script> 
</head> 
<body> 
</body> 
</html>