Как вы явно устанавливаете новое свойство на `window` в TypeScript?
Я устанавливаю глобальные пространства имен для своих объектов, явно устанавливая свойство на window
.
window.MyNamespace = window.MyNamespace || {};
TypeScript подчеркивает MyNamespace
и жалуется, что:
Свойство 'MyNamespace' не существует при значении типа 'window' любой "
Я могу заставить код работать, объявив MyNamespace
в качестве переменной окружения и отбрасывая window
эксплицитно, но я не хочу этого делать.
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
Как я могу сохранить window
там и сделать TypeScript счастливым?
В качестве побочного примечания мне особенно забавно, что TypeScript жалуется, так как он говорит мне, что window
имеет тип any
, который определенно может содержать что угодно.
Ответы
Ответ 1
Просто нашел ответ на этот вопрос в fooobar.com/questions/33645/....
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
В основном вам необходимо расширить существующий интерфейс window
, чтобы рассказать об этом новом свойстве.
Ответ 2
Чтобы сохранить динамику, просто используйте:
(<any>window).MyNamespace
Ответ 3
КАК ТИПИСКРИПТ ^ 3.4.3 НАСТОЯЩЕГО РЕШЕНИЯ НЕ ДЕЙСТВУЕТ
Или же...
Вы можете просто набрать:
window['MyNamespace']
и вы не получите ошибку компиляции, и она работает так же, как набрав window.MyNamespace
Ответ 4
Использование TSX? Ни один из других ответов не работал на меня.
Вот что я сделал:
(window as any).MyNamespace
Ответ 5
Принятый ответ - это то, что я использовал, но с TypeScript 0.9. * он больше не работает. Новое определение интерфейса Window
похоже, полностью заменяет встроенное определение, а не увеличивает его.
Вместо этого я сделал это:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
ОБНОВЛЕНИЕ: С TypeScript 0.9.5 принятый ответ снова работает.
Ответ 6
Если вам нужно расширить объект window
с помощью специального типа, который требует использования import
, вы можете использовать следующий метод:
window.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
См. "Глобальное увеличение" в разделе "Объединение декларации" Справочника: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation
Ответ 7
Глобальные являются "злом" :), я думаю, что лучший способ иметь также переносимость:
Сначала вы экспортируете интерфейс: (например:./custom.window.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
Второй вы импортируете
import {CustomWindow} from './custom.window.ts';
Третье приведенное глобальное окно var с CustomWindow
declare let window: CustomWindow;
Таким образом, у вас также не будет красной линии в другой IDE, если вы используете существующие атрибуты объекта окна, поэтому в конце попробуйте:
window.customAttribute = 'works';
window.location.href = '/works';
Протестировано с Typescript 2.4.x и новее!
Ответ 8
Мне не нужно делать это очень часто, единственный случай, который у меня был, был при использовании Redux Devtools с промежуточным программным обеспечением.
Я просто сделал:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
Или вы могли бы сделать:
let myWindow = window as any;
а затем myWindow.myProp = 'my value';
Ответ 9
Для тех, кто использует Angular CLI, это довольно просто:
SRC/polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
мой обычай-utils.ts
window.myCustomFn = function () {
...
};
Если вы используете IntelliJ, вам также необходимо изменить следующие настройки в среде IDE, прежде чем поднять новые полифиллы:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
Ответ 10
Большинство других ответов не являются идеальными.
- Некоторые из них просто подавляют вывод типа для магазина.
- Некоторые другие заботятся только о глобальной переменной как о пространстве имен, но не как интерфейс/класс
Я также сталкиваюсь с подобной проблемой этим утром. Я пробовал так много "решений" на 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
(свойство window).
Ответ 11
После поиска ответов, я думаю, что эта страница может быть полезной. https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation Не уверен насчет истории слияния объявлений, но он объясняет, почему может работать следующее.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Ответ 12
Здесь, как это сделать, если вы используете 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 || {};
Ответ 13
Для справки (это правильный ответ):
Внутри файла определения .d.ts
type MyGlobalFunctionType = (name: string) => void
Если вы работаете в браузере,
вы добавляете участников в контекст окна браузера, открывая интерфейс Window:
interface Window {
myGlobalFunction: MyGlobalFunctionType
}
Такая же идея для NodeJS:
declare module NodeJS {
interface Global {
myGlobalFunction: MyGlobalFunctionType
}
}
Теперь вы объявляете корневую переменную (которая фактически будет жить в окне или глобальном)
declare const myGlobalFunction: MyGlobalFunctionType;
Затем в регулярном файле .ts
, но импортированном как побочный эффект, вы фактически реализуете его:
global/* or window */.myGlobalFunction = function (name: string) {
console.log("Hey !", name);
};
И, наконец, используйте его в другом месте в базе кода: либо
global/* or window */.myGlobalFunction("Kevin");
myGlobalFunction("Kevin");
Ответ 14
Создание настраиваемого интерфейса расширяет окно и добавляет ваше настраиваемое свойство как необязательное.
Затем позвольте customWindow, использующему пользовательский интерфейс, но оцененному с помощью исходного окна.
Он работал с [email protected]
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
Ответ 15
Typscript не выполняет проверку типов в свойствах строки.
window["newProperty"] = customObj;
В идеале сценарий глобальной переменной следует избегать. Я использую его иногда для отладки объекта в консоли браузера.
Ответ 16
Если вы используете Typescript 3.x, вы можете пропустить declare global
часть в других ответах и вместо этого просто использовать:
interface Window {
someValue: string
another: boolean
}
Это работало со мной при использовании Typescript 3.3, WebPack и TSLint.
Ответ 17
Для тех, кто хочет установить вычисляемое или динамическое свойство для объекта window
, вы обнаружите, что это невозможно с помощью метода declare global
. Чтобы уточнить для этого варианта использования
window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature
Вы можете попытаться сделать что-то вроде этого
declare global {
interface Window {
[DyanmicObject.key]: string; // error RIP
}
}
Выше будет ошибка, хотя. Это связано с тем, что в Typescript интерфейсы плохо работают с вычисляемыми свойствами и выдают ошибку вроде
A computed property name in an interface must directly refer to a built-in symbol
Чтобы обойти это, вы можете перейти с предложением приведения window
к <any>
чтобы вы могли сделать
(window as any)[DynamicObject.key]
Ответ 18
Я хотел использовать это в библиотеке Angular (6) сегодня, и мне потребовалось некоторое время, чтобы заставить это работать как ожидалось.
Чтобы моя библиотека использовала объявления, мне пришлось использовать расширение d.ts
для файла, который объявляет новые свойства глобального объекта.
Итак, в конце концов, файл закончился чем-то вроде:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
После создания не забудьте выставить его в свой public_api.ts
.
Это сделало это для меня. Надеюсь это поможет.
Ответ 19
Когда я попробовал это, window
набрал значение window
- это означает, что есть определение, которое указывает, какие свойства и методы поддерживает window
, а ваше собственное пространство имен отсутствует в этом списке.
Не можете ли вы получить нужное поведение с помощью модуля TypeScript?
module MyNamespace {
export class Example {
}
}
Ответ 20
Сначала вам нужно объявить объект окна в текущей области видимости.
Потому что машинопись хочет знать тип объекта.
Поскольку объект окна определен где-то еще, вы не можете переопределить его.
Но вы можете заявить об этом следующим образом:
declare var window: any;
Это не переопределит объект окна или не создаст другую переменную с именем window
.
Это означает, что окно определено где-то еще, и вы просто ссылаетесь на него в текущей области видимости.
Затем вы можете обратиться к своему объекту MyNamespace просто: -
window.MyNamespace
Или вы можете установить новое свойство для объекта window
просто:
window.MyNamespace = MyObject
И теперь машинопись не будет жаловаться.