Как вы явно устанавливаете новое свойство в "window" в TypeScript?

я настраиваю глобальные пространства имен для своих объектов, явно устанавливая свойство на window.

window.MyNamespace = window.MyNamespace || {};

шрифт подчеркивает MyNamespace и жалуется, что:

свойство "MyNamespace" не существует для значения типа "window" любой"

Я могу заставить код работать, объявив MyNamespace как окружающая переменная и падение window эксплицитности, но я не хочу этого делать.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

как я могу держать window там и сделать TypeScript счастливым?

в качестве примечания я нахожу особенно забавным, что TypeScript жалуется, так как он говорит мне, что window типа any который определенно может содержать что угодно.

14 ответов


чтобы сохранить динамичность, просто используйте:

(<any>window).MyNamespace

только что нашел ответ на этот вопрос в ответ на другой вопрос StackOverflow.

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

в основном вам нужно продлить существующий window интерфейс, чтобы рассказать ему о Вашем новом свойстве.


или...

вы можете просто ввести:

window['MyNamespace']

и вы не получите ошибку компиляции, и она работает так же, как пишите window.MyNamespace


использование TSX? Ни один из других ответов не работал на меня.

вот что я сделал:

(window as any).MyNamespace

принятый ответ - это то, что я использовал, но с TypeScript 0.9.* он больше не работает. Новое определение Window интерфейс, похоже, полностью заменяет встроенное определение, а не увеличивает его.

я взялся делать это вместо этого:

interface MyWindow extends Window {
    myFunction(): void;
}

declare var window: MyWindow;

обновление: С TypeScript 0.9.5 принятый ответ снова работает.


Если вам нужно продлить window объект с пользовательским типом, который требует использования import вы можете использовать следующий метод:


Global-это "зло":), я думаю, что лучший способ иметь также переносимость:

сначала вы экспортируете интерфейс: (например: ./обычай.окно.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

второй импортировать

import {CustomWindow} from './custom.window.ts';

третье литое глобальное окно var с CustomWindow

declare let window: CustomWindow;

таким образом, у вас нет также красной линии в другой IDE, если вы используете с существующими атрибутами объекта window, поэтому в конце попробуйте:

window.customAttribute = 'works';
window.location.href = '/works';

протестировано с помощью Typescript 2.4.x


вот как это сделать, если вы используете Менеджер Определения TypeScript!

npm install typings --global

создать typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

установите пользовательский ввод:

typings install file:typings/custom/window.d.ts --save --global

готово, используйте его! Typescript больше не будет жаловаться:

window.MyNamespace = window.MyNamespace || {};

большинство других ответов не идеальны.

  • некоторые из них просто подавить вывод типа для магазина.
  • некоторые из других заботятся только о глобальной переменной как пространстве имен, но не как интерфейс/класс

Я также сталкиваюсь с аналогичной проблемой сегодня утром. Я пробовал так много "решений" на SO, но ни одно из них не дает никакой ошибки типа абсолютно и не позволяет запускать прыжки типа в IDE(webstorm или vscode).

наконец, отсюда

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

, Я нахожу разумное решение для прикрепить типы для глобальной переменной, которая действует как интерфейс / класс и пространство имен.

пример ниже:

// typings.d.ts
declare interface Window {
    myNamespace?: MyNamespace & typeof MyNamespace
}

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

теперь код выше объединяет типы пространства имен MyNamespace интерфейс MyNamespace в глобальную переменную myNamespace(собственность окно.)


мне не нужно делать это очень часто, единственный случай, который у меня был, был при использовании Redux Devtools с middleware.

Я просто сделал:

const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

или вы могли бы сделать:

let myWindow = window as any;

а то myWindow.myProp = 'my value';


Если вы используете угловой CLI это действительно просто (протестировано на CLI RC.0):

src / polyfills.ТС

declare global {
  interface Window {
    myCustomFn: () => void;
  }
}

my-custom-utils.ТС

window.myCustomFn = function () {
  ...
};

Я использую IntelliJ, поэтому мне также нужно было изменить следующую настройку в IDE, прежде чем мои новые polyfills подобрали:

> File 
> Settings 
> Languages & Frameworks 
> TypeScript 
> check 'Use TypeScript Service'.

Для справки (это правильный ответ):

внутри .d.ts файл определения

type MyGlobalFunctionType = (name: string) => void

если вы работаете в браузере, вы добавляете членов в контекст окна браузера, открывая интерфейс окна:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

та же идея для NodeJS:

declare module NodeJS {
  interface Global {
    myGlobalFunction: MyGlobalFunctionType
  }
}

теперь вы объявляете корневую переменную (которая фактически будет жить в window или global)

declare const myGlobalFunction: MyGlobalFunctionType;

тогда в обычном .ts файл, но импортированный как побочный эффект, вы на самом деле реализовать это:

global/* or window */.myGlobalFunction = function (name: string) {
  console.log("Hey !", name);
};

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

global/* or window */.myGlobalFunction("Kevin");

myGlobalFunction("Kevin");

после поиска ответов вокруг, я думаю, что эта страница может быть полезна. https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation Не уверен в истории слияния деклараций, но это объясняет, почему может работать следующее.

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

Я хотел использовать это в угловой (6) библиотеке сегодня, и мне потребовалось некоторое время, чтобы заставить это работать, как ожидалось.

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

Итак, в конце концов, файл закончился чем-то вроде:

/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts

после создания, не забудьте выставить его в вашем public_api.ts.

Это сделало это для меня. Надеюсь, это поможет.