How do you explicitly set a new property on `window` in TypeScript?
我通过在
1 | window.MyNamespace = window.MyNamespace || {}; |
typescript在
The property 'MyNamespace' does not exist on value of type 'window'
any"
号
我可以通过将
1 2 3 | declare var MyNamespace: any; MyNamespace = MyNamespace || {}; |
号
我怎样才能让
作为旁注,我发现typescript的抱怨特别有趣,因为它告诉我
刚刚在另一个stackoverflow问题的答案中找到了答案。
1 2 3 4 5 | declare global { interface Window { MyNamespace: any; } } window.MyNamespace = window.MyNamespace || {}; |
基本上,您需要扩展现有的
要保持动态,只需使用:
1 | (window).MyNamespace |
。
从typescript ^3.4.3开始,此解决方案不再有效
或者…
您只需键入:
1 | window['MyNamespace'] |
号
您不会得到编译错误,它的工作原理与键入
使用TSX?其他答案对我来说都不管用。
我是这样做的:
1 | (window as any).MyNamespace |
接受的答案是我以前用过的,但是用了0.9.*字体,它就不工作了。
我已经开始这样做了:
1 2 3 4 5 | interface MyWindow extends Window { myFunction(): void; } declare var window: MyWindow; |
更新:使用typescript 0.9.5,接受的答案将再次工作。
如果需要使用需要使用
窗口.d.ts
1 2 3 4 5 6 7 | import MyInterface from './MyInterface'; declare global { interface Window { propName: MyInterface } } |
。
请参见手册"声明合并"部分中的"全局扩充":https://www.typescriptlang.org/docs/handbook/declaration merging.html全局扩充
全球都是"邪恶的":)我认为拥有可移植性的最好方法是:
首先导出接口:(例如:/custom.window.ts)
1 2 3 | export interface CustomWindow extends Window { customAttribute: any; } |
。
第二次导入
1 | import {CustomWindow} from './custom.window.ts'; |
号
第三个具有自定义窗口的强制转换全局变量窗口
1 | declare let window: CustomWindow; |
号
通过这种方式,如果您使用window对象的现有属性,那么在不同的ide中也没有红线,因此最后尝试:
1 2 | window.customAttribute = 'works'; window.location.href = '/works'; |
用typescript 2.4.x测试
我不需要经常这样做,我只有在使用ReduxDevTools和中间件时才会这样做。
我只是做了:
1 | const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; |
或者你可以这样做:
江户十一〔11〕。
然后是
如果您使用的是Angular CLI,那么非常简单:
SRC/Polyfills.ts型
1 2 3 4 5 | declare global { interface Window { myCustomFn: () => void; } } |
号
我的自定义实用程序
1 2 3 | window.myCustomFn = function () { ... }; |
号
如果您使用的是Intellij,则在新的polyfills拾取之前,还需要在IDE中更改以下设置:
1 2 3 4 5 | > File > Settings > Languages & Frameworks > TypeScript > check 'Use TypeScript Service'. |
号
在找到答案后,我认为这个页面可能会有所帮助。https://www.typescriptlang.org/docs/handbook/declaration merging.html全局扩充不确定声明合并的历史,但它解释了以下内容可以工作的原因。
1 2 3 4 5 | declare global { interface Window { MyNamespace: any; } } window.MyNamespace = window.MyNamespace || {}; |
其他大多数答案都不完美。
- 其中一些只是抑制了Shop的类型推断。
- 其他一些只关心全局变量作为名称空间,而不是作为接口/类。
今天早上我也遇到了类似的问题。我尝试了这么多这样的"解决方案",但它们中没有一个绝对不会产生类型错误,并且能够在IDE中触发类型跳转(webstorm或vscode)。
最后,从这里开始
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
号
我找到了一个合理的解决方案来附加作为接口/类和命名空间的全局变量的类型。
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 | // typings.d.ts declare interface Window { myNamespace?: MyNamespace & typeof MyNamespace } declare interface MyNamespace { somemethod?() } declare namespace MyNamespace { // ... } |
现在,上面的代码将名称空间
如果您使用的是typescript定义管理器,下面介绍如何执行此操作!
1 | npm install typings --global |
。
创建
1 2 3 4 5 | interface Window { MyNamespace: any; } declare var window: Window; |
安装自定义键入:
1 | typings install file:typings/custom/window.d.ts --save --global |
。
完成,使用它‌!typescript不会再抱怨了:
1 | window.MyNamespace = window.MyNamespace || {}; |
供参考(这是正确答案):
在
1 | type MyGlobalFunctionType = (name: string) => void |
号
如果在浏览器中工作,通过重新打开窗口的界面,可以将成员添加到浏览器的窗口上下文中:
1 2 3 | interface Window { myGlobalFunction: MyGlobalFunctionType } |
号
Nodejs的想法相同:
1 2 3 4 5 | declare module NodeJS { interface Global { myGlobalFunction: MyGlobalFunctionType } } |
号
现在,您声明根变量(它将实际位于窗口或全局上)
1 | declare const myGlobalFunction: MyGlobalFunctionType; |
号
然后在一个常规的
1 2 3 | global/* or window */.myGlobalFunction = function (name: string) { console.log("Hey !", name); }; |
号
最后在代码库的其他地方使用它,可以使用:
1 2 3 | global/* or window */.myGlobalFunction("Kevin"); myGlobalFunction("Kevin"); |
号
使自定义接口扩展窗口并将自定义属性添加为可选。
然后,让使用自定义接口但与原始窗口一起值的custom window。
它与[email protected]一起工作。
1 2 3 4 5 6 7 | interface ICustomWindow extends Window { MyNamespace?: any } const customWindow:ICustomWindow = window; customWindow.MyNamespace = customWindow.MyNamespace {} |
如果您使用的是typescript 3.x,则可以在其他答案中省略
1 2 3 4 | interface Window { someValue: string another: boolean } |
号
在使用typescript 3.3、webpack和tslint时,这对我很有用。
我今天想在一个角度(6)的图书馆使用这个,我花了一段时间才使它按预期工作。
为了让我的库使用声明,我必须对声明全局对象新属性的文件使用
最后,文件的结尾是:
江户十一〔一〕号
一旦创建,不要忘记在你的
那是为了我。希望这有帮助。
对于那些想要在
1 | window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature |
你可能会尝试这样做
1 2 3 4 5 | declare global { interface Window { [DyanmicObject.key]: string; // error RIP } } |
。
但是,上面的内容会出错。这是因为在typescript中,接口不能很好地处理计算属性,并且会引发如下错误
1 | A computed property name in an interface must directly refer to a built-in symbol |
为了解决这个问题,你可以建议把
1 | (window as any)[DynamicObject.key] |
。
首先,您需要在当前作用域中声明窗口对象。因为typescript想要知道对象的类型。因为窗口对象是在其他地方定义的,所以不能重新定义它。但你可以声明如下:
1 | declare var window: any; |
。
这不会重新定义窗口对象,也不会创建另一个名为
然后,您可以通过以下方式引用mynamespace对象:
1 | window.MyNamespace |
或者您可以通过以下方法在
1 | window.MyNamespace = MyObject |
。
现在打字稿也不会抱怨了。