2013-12-23 3 views
2

Прежде чем продолжить мой вопрос, позвольте мне указать, что я уже провел значительное исследование этой темы и уже задал пару связанных вопросов, которые вы можете найти здесь:Полиполки, прокладки и удлинители с использованием TypeScript

Extending Object.prototype with TypeScript

Extending instance/static functions on existing prototypes with TypeScript

Хотя машинопись, кажется, зреет достаточно хорошо вместе это путь к версии 1.0, я заметил довольно рано, в его младенчестве, что это было не легко polyfill/прокладки/патч обезьяны/расширить функциональность основных объектов (Object, Stri ng, Number, Boolean и т. д.) с использованием TypeScript ... однако это совершенно законно в чистом JavaScript и, на мой взгляд, необходимо для создания совместимых с API и совместимых с ним браузеров.

Теперь, когда мы находимся на версии 0.9.5, я заметил значительное улучшение в этой области, и теперь мы можем расширить прототип основных объектов, и, похоже, мы также можем добавлять статические функции к основным объектам. ..Что ... это, похоже, глючит!

Рассмотрим следующий пример кода:

interface Object { 
    /********************************/ 
    /* Static functions   */ 
    /********************************/ 

    // ECMAScript 6 Object.is function 
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 
    is(v1: any, v2: any): boolean; 

    /********************************/ 
    /* Prototype functions   */ 
    /********************************/ 

    // Custom method for testing obejct equality (based on Java/C# principles) 
    equals(obj: any): boolean; 
} 

// Object.is polyfill 
(() => { 
    if(!Object.is) { 
     Object.is = function(v1: any, v2: any): boolean { 
      if (v1 === 0 && v2 === 0) { 
       return 1/v1 === 1/v2; 
      } 
      if (v1 !== v1) { 
       return v2 !== v2; 
      } 
      return v1 === v2; 
     } 
    } 
})(); 

// Object.prototype.equals implementation 
Object.prototype.equals = function(obj: any): boolean { 
    return Object.is(obj, this); 
} 

Хотите играть с ним ... Playground

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

declare var Object: { 
    new (value?: any): Object; 
    (): any; 
    (value: any): any; 
    prototype: Object; 
    getPrototypeOf(o: any): any; 
    getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor; 
    getOwnPropertyNames(o: any): string[]; 
    create(o: any, properties?: PropertyDescriptorMap): any; 
    defineProperty(o: any, p: string, attributes: PropertyDescriptor): any; 
    defineProperties(o: any, properties: PropertyDescriptorMap): any; 
    seal(o: any): any; 
    freeze(o: any): any; 
    preventExtensions(o: any): any; 
    isSealed(o: any): bool; 
    isFrozen(o: any): bool; 
    isExtensible(o: any): bool; 
    keys(o: any): string[]; 
} 

Так это означает, что мы должны быть действительно добавление is(v1: any, v2: any): boolean; к объявлению ... но заявления в машинописном не открыты как и интерфейсы, поэтому это невозможно.

Это означает, что если я удалю декларацию из интерфейса, TypeScript тогда жалуется, что Object.is не существует ... так что мне кажется, что я должен иметь его там, чтобы полиполк работал!

«Хорошо, если это сработает ... в чем проблема?» - Да, это работает, но только так, и это не изящно.

Поскольку есть реализован статически, но она сжимается как часть объекта, машинопись IntelliSense по-прежнему ожидает Object.prototype.is и не признает существование Object.is

Я чувствую, что я болтовню в настоящее время, так что я буду доходите до сути.

  1. Это известная проблема?
  2. Я что-то пропустил?
  3. Что необходимо для исправления этой проблемы?

Примечание: Я только что заметил, кажется, что вы можете переписать заявления сейчас, так что вы могли бы добавить is(v1: any, v2: any): boolean; к декларации путем перезаписи его полностью ... но я все еще чувствую, что это не самый элегантное решение.

ответ

2

Эта проблема была поднята.Основными причинами неименования типа Object var были то, что мы хотели вообще не создавать имя (что бы вы назвали его?), И что в будущем это затруднит переход этого типа в класс формы, не вызывая нарушения.

Лучшим решением на вашем конце является создание пользовательского lib.d.ts для вашего проекта; до тех пор, пока компилятор может найти некоторые типы с именами примитивных типов (Number, String и т. д.), на самом деле не имеет значения, что такое содержимое lib.d.ts. Таким образом, вы можете либо иметь, например, lib-es6.d.ts, которые добавили новых членов непосредственно к анонимным типам или, например, lib-extensible.d.ts, которые изменили анонимные типы на именованные интерфейсы, чтобы вы могли распространять их в файле определения полина в другом месте.

+1

Я не совсем уверен, что полностью понимаю ваши аргументы, хотя ясно, что вы хорошо осведомлены о дизайне TypeScript. Я не уверен, почему вы хотите в будущем преобразовывать объекты, такие как Object, String, Number и т. Д., Поскольку классы в TypeScript генерируют реализацию, тогда как эти объекты предоставляются изначально средой выполнения. Поэтому представляется более целесообразным просто объявить их реализацию компилятору в TypeScript (если это имеет смысл). Я хочу сказать, что декларация «должна/могла» быть открыта как с интерфейсами, поэтому статические члены также могут быть добавлены. – series0ne

Смежные вопросы