Расширение прототипа встроенного класса в Typescript 2.8+ - PullRequest
0 голосов
/ 26 апреля 2018

Это не работает

interface String {
    contains(s:string):boolean;
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;

, потому что Property 'contains' does not exist on type 'String'

Это немного удивительно, так как добавление этого текста было полной целью объявления интерфейса.http://www.typescriptlang.org/docs/handbook/declaration-merging.html предполагает, что приведенный выше код является законным.Насколько я могу судить, String находится в глобальном пространстве имен, изучив lib.es2015.wellknown.d.ts.

Как правильно поступить?После прочтения Расширяемого стороннего модуля Алуана Хаддада, который открыт для всех , я переписал так:

declare global {
    interface String {
        contains(s: string): boolean;
    }
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;

, и изменение интерфейса теперь корректно.Но теперь 'this' implicitly has type 'any' because it does not have a type annotation.

В соответствии с дальнейшими комментариями this можно явно набрать, используя синтаксис функции.

String.prototype.contains = function (this: string, s:string):boolean { 
    return this.indexOf(s)!==-1; 
};

Следует также отметить, что в ходе этого исследования я обнаружил, что contains реализован с именем includes и объявлен в lib.es2015.core.d.ts

1 Ответ

0 голосов
/ 26 апреля 2018

Если вы определяете расширение внутри модуля, то есть файл, содержащий import или export верхнего уровня, то вам необходимо использовать блок declare global для расширения глобальной области видимости.В противном случае объявленный вами интерфейс не будет объединен с интерфейсом глобального массива, поскольку он является локальным для модуля, как и любое другое объявление.Объявить глобальный синтаксис специально для этого случая использования.

Кроме того, когда вы определяете фактический метод, вы не можете использовать функцию стрелки, если сам метод определен в терминах this, потому что функции стрелки имеютстатическая область действия this, в то время как динамическая this необходима для методов.

Соединение ее

//  this is a module
export {}

declare global {
  interface String {
    contains(other: string): boolean;
  }
} 

String.prototype.contains = function (other) {
  return this.indexOf(other) and !== -1;
};

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

...