我通过显式设置窗口上的属性为我的对象设置全局名称空间。
window.MyNamespace = window.MyNamespace || {};
TypeScript强调MyNamespace,并抱怨:
属性“MyNamespace”在类型为“window”的值上不存在
任何“
我可以通过将MyNamespace声明为环境变量并删除窗口显式来使代码工作,但我不想这样做。
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
我如何保持窗口在那里,让TypeScript满意?
作为旁注,我发现特别有趣的是,TypeScript抱怨,因为它告诉我,窗口的类型是any,它肯定可以包含任何东西。
下面是如何做到这一点,如果你使用的是TypeScript定义管理器!
npm install typings --global
创建输入/定制/ 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 || {};
对于那些使用Angular CLI的人来说,这很简单:
文件src / polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
文件my-custom-utils.ts
window.myCustomFn = function () {
...
};
如果你正在使用IntelliJ IDEA,你还需要在IDE中更改以下设置,然后你的新腻子才会开始:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
供参考(这是正确答案):
在。d里面。Ts定义文件
type MyGlobalFunctionType = (name: string) => void
如果你在浏览器中工作,你可以通过重新打开window的界面将成员添加到浏览器的窗口上下文:
interface Window {
myGlobalFunction: MyGlobalFunctionType
}
Node.js也是这样:
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");
其他大多数答案都不完美。
其中一些只是为了显示而抑制了类型推断。
其他一些只关心全局变量作为名称空间,而不关心接口/类
今天早上我也遇到了一个类似的问题。我在Stack Overflow上尝试了很多“解决方案”,但没有一个完全没有类型错误,并在IDE中启用触发类型跳转(WebStorm或Visual Studio Code)。
最后,从允许模块定义声明为全局变量#3180
我找到了一个合理的解决方案,为同时充当接口/类和名称空间的全局变量附加类型。
例子如下:
// typings.d.ts
declare interface Window {
myNamespace?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
上面的代码将命名空间MyNamespace和接口MyNamespace的类型合并到全局变量MyNamespace (window的属性)中。
全局变量是“邪恶的”:)我认为拥有可移植性的最好方法是:
首先导出接口:(例如,./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和最新!
对于那些想要在窗口对象上设置计算或动态属性的人,你会发现使用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
为了解决这个问题,你可以按照建议将窗口转换为<any>
(window as any)[DynamicObject.key]
[2022]:我们必须在React或Nextjs项目中扩展“window”对象。
我们可以通过下面的步骤来解决这个问题。
在src文件夹名称中创建一个文件夹作为类型。
在类型文件夹中创建一个名为index.d.ts的文件
将这段代码写在index.d.ts文件中。
出口{};
声明全局{
窗口{
名称空间:任何;
}
}
窗口。名称空间=窗口。名称空间| | {};
保存该文件。
现在最后一个变化。
修改“tsConfig. conf”json文件。来继承节点模块类型和我们的类型。
{
"compilerOptions": {
...
"typeRoots": [
"./node_modules/@types",
"./src/types"
],
....
}