我通过在window
上显式设置属性为我的对象设置全局命名空间。
window.MyNamespace = window.MyNamespace || {};
TypeScript强调MyNamespace
并抱怨:
属性'MyNamespace'在'window'类型的值上不存在 任何“
我可以通过将MyNamespace
声明为环境变量并删除window
显式但我不想这样做来使代码工作。
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
如何将window
保留在那里并使TypeScript满意?
作为旁注,我发现TypeScript抱怨特别有趣,因为它告诉我window
类型为any
,它绝对可以包含任何内容。
答案 0 :(得分:410)
在another StackOverflow question's answer中找到答案。
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
基本上,您需要扩展现有的window
界面,告诉它您的新属性。
答案 1 :(得分:337)
要保持动态,只需使用:
(<any>window).MyNamespace
答案 2 :(得分:169)
AS OF TYPESCRIPT ^ 3.4.3此解决方案不再起作用
或者...
你可以输入:
window['MyNamespace']
并且您不会收到编译错误,它与键入window.MyNamespace
答案 3 :(得分:58)
接受的答案是我以前使用的,但使用TypeScript 0.9。*它不再有效。 Window
接口的新定义似乎完全取代了内置定义,而不是对其进行扩充。
我已采取这样做:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
更新:使用TypeScript 0.9.5,已接受的答案将重新开始。
答案 4 :(得分:38)
如果您需要使用需要使用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
答案 5 :(得分:31)
全球是“邪恶的”:),我认为具有便携性的最佳方式是:
首先导出界面:(例如:./ custom.window.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
第二次导入
import {CustomWindow} from './custom.window.ts';
使用CustomWindow
创建第三个全局变量窗口declare let window: CustomWindow;
这样,如果你使用窗口对象的现有属性,你在不同的IDE中也没有红线,所以最后试试:
window.customAttribute = 'works';
window.location.href = '/works';
使用Typescript 2.4.x进行测试
答案 6 :(得分:24)
我不需要经常这样做,我唯一的情况是将Redux Devtools与中间件一起使用。
我只是这样做了:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
或者你可以这样做:
let myWindow = window as any;
然后myWindow.myProp = 'my value';
答案 7 :(得分:23)
创建一个名为global.d.ts
的文件,例如/src/@types/global.d.ts
,然后定义如下接口:
interface Window {
myLib: any
}
ref:https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-d-ts.html
答案 8 :(得分:13)
如果你正在使用 Angular CLI ,那真的很简单:
的src / polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
MY-定制utils.ts
window.myCustomFn = function () {
...
};
如果您正在使用IntelliJ,则还需要在新的polyfill选择之前在IDE中更改以下设置:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
答案 9 :(得分:12)
其他大多数答案并不完美。
今天早上我也遇到了类似的问题。我尝试了很多&#34;解决方案&#34;在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
(窗口的属性)中。
答案 10 :(得分:12)
在找到答案后,我认为此页面可能会有所帮助。 https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation 不确定声明合并的历史,但它解释了为什么以下可行。
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
答案 11 :(得分:10)
如果您使用的是TypeScript Definition Manager , 创建 安装自定义输入: 完成,使用它! 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
window.MyNamespace = window.MyNamespace || {};
答案 12 :(得分:9)
使用create-react-app v3.3,我发现最简单的方法是在自动生成的Window
中扩展react-app-env.d.ts
类型:
interface Window {
MyNamespace: any;
}
答案 13 :(得分:8)
使用
window["MyNamespace"] = window["MyNamespace"] || {};
使用字符串属性应该没问题,但是如果您确实希望有一个单独的窗口并组织代码,则可以扩展窗口对象:
interface MyNamespacedWindow extends Window {
MyNamespace: object;
}
declare var window: MyNamespacedWindow;
答案 14 :(得分:5)
使自定义界面扩展Window并将您的自定义属性添加为可选属性。
然后,让customWindow使用自定义界面,但与原始窗口一起使用。
它与typescript@3.1.3。一起使用
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
答案 15 :(得分:4)
供参考(这是正确答案):
在.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");
答案 16 :(得分:4)
如果您使用的是Typescript 3.x,则可以省略其他答案中的declare global
部分,而只需使用:
interface Window {
someValue: string
another: boolean
}
在使用Typescript 3.3,WebPack和TSLint时,这与我一起工作。
答案 17 :(得分:4)
从 3.4 版开始,TypeScript 已经支持 globalThis
。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#type-checking-for-globalthis
// in a global file:
var abc = 100;
// Refers to 'abc' from above.
globalThis.abc = 200;
“全局”文件是没有导入/导出语句的文件。所以声明 var abc;
可以写成 .d.ts。
答案 18 :(得分:2)
我今天想在Angular(6)库中使用它,我花了一些时间才能使它按预期工作。
为了使我的库使用声明,我必须对声明全局对象新属性的文件使用d.ts
扩展名。
所以最后,文件最终显示为:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
创建后,请不要忘记将其暴露在您的public_api.ts
中。
对我来说就做到了。希望这会有所帮助。
答案 19 :(得分:2)
对于那些想在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]
答案 20 :(得分:2)
打字稿不对字符串属性进行类型检查。
window["newProperty"] = customObj;
理想情况下,应避免使用全局变量方案。有时我会用它来调试浏览器控制台中的对象。
答案 21 :(得分:1)
typescript防止在不分配具有所需属性的类型的情况下访问对象,或者
已经分配给any
,因此您可以使用可选的链接window?.MyNamespace = 'value'
。
答案 22 :(得分:0)
首先,您需要在当前范围内声明窗口对象。
因为打字稿想知道对象的类型。
由于窗口对象是在其他位置定义的,因此无法重新定义它。
但您可以声明如下:-
declare var window: any;
这不会重新定义窗口对象,也不会创建名称为window
的另一个变量。
这意味着窗口是在其他地方定义的,您只是在当前作用域中引用它。
然后,您可以通过以下方式简单地引用MyNamespace对象:-
window.MyNamespace
现在打字稿也不会抱怨。