首页 文章

你如何在TypeScript中的`window`上显式设置一个新属性?

提问于
浏览
320

我通过在 window 上显式设置属性来为我的对象设置全局命名空间 .

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

TypeScript强调 MyNamespace 并抱怨:

属性'MyNamespace'在'window'类型的值上不存在任何“

我可以通过将 MyNamespace 声明为环境变量并删除 window 显式来使代码工作,但我不想这样做 .

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

如何在那里保留 window 并使TypeScript满意?

作为旁注,我发现TypeScript抱怨特别有趣,因为它告诉我 window 的类型为 any ,绝对可以包含任何内容 .

15 回答

  • 14

    这里's how to do it, if you'重新使用TypeScript Definition Manager

    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 || {};
    
  • 2

    使用TSX?没有其他答案对我有用 .

    这是我做的:

    (window as any).MyNamespace
    
  • 53

    如果你正在使用 Angular CLI 它真的很简单(在CLI RC.0上测试):

    SRC / polyfills.ts

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

    我定制,utils.ts

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

    我正在使用IntelliJ,所以在新的polyfill拾取之前我还需要在IDE中更改以下设置:

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

    要么...

    你可以输入:

    window['MyNamespace']
    

    并且你不会得到编译错误,它的工作方式与输入 window.MyNamespace 相同

  • 114

    刚刚在another StackOverflow question's answer找到了答案 .

    declare global {
        interface Window { MyNamespace: any; }
    }
    
    window.MyNamespace = window.MyNamespace || {};
    

    基本上你需要扩展现有的 window 界面来告诉它你的新房产 .

  • 149

    全球是“邪恶的”:),我认为具有可移植性的最佳方式是:

    首先导出界面:(例如:./ custom.window.ts)

    export interface CustomWindow extends Window {
        customAttribute: any;
    }
    

    其次你导入

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

    使用CustomWindow的第三个全局变量窗口

    declare let window: CustomWindow;
    

    这样,如果你使用window对象的现有属性,你在不同的IDE中也没有红线,所以最后尝试:

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

    使用Typescript 2.4.x进行测试

  • 0

    我今天想在Angular(6)库中使用它,我花了一些时间才能按预期工作 .

    为了让我的库使用声明,我必须使用 d.ts extention来声明全局对象的新属性 .

    所以最后,文件结果如下:

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

    创建后,不要忘记在 public_api.ts 中公开它 .

    这样做对我而言 . 希望这可以帮助 .

  • 4

    接受的答案是我以前使用的,但使用TypeScript 0.9 . *它不再有效 . Window 接口的新定义似乎完全取代了内置定义,而不是对其进行扩充 .

    我采取了这样做:

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

    UPDATE: 使用TypeScript 0.9.5,接受的答案再次起作用 .

  • 33

    为了保持动态,只需使用:

    (<any>window).MyNamespace
    
  • 7

    大多数其他答案并不完美 .

    • 其中一些只是抑制了商店的类型推断 .

    • 其他一些人只关心全局变量作为命名空间,而不是接口/类

    今天早上我也遇到了类似的问题 . 我在SO上尝试了很多“解决方案”,但它们都没有绝对产生类型错误,并且在IDE(webstorm或vscode)中启用触发类型跳转 .

    最后,从这里开始

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

    ,我找到了 attach typings for global variable which acts as interface/class and namespace both 的合理解决方案 .

    示例如下:

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

    现在,上面的代码将命名空间 MyNamespace 和接口 MyNamespace 的类型合并到全局变量 myNamespace (窗口的属性)中 .

  • 9

    我不需要经常这样做,我唯一的情况是使用Redux Devtools和中间件 .

    我只是做了:

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

    或者你可以这样做:

    let myWindow = window as any;

    然后 myWindow.myProp = 'my value';

  • 5

    找到答案后,我认为这个页面可能会有所帮助 . https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation不确定声明合并的历史,但它解释了为什么以下方法可行 .

    declare global {
        interface Window { MyNamespace: any; }
    }
    
    window.MyNamespace = window.MyNamespace || {};
    
  • 24

    供参考(这是正确答案):

    .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");
    
  • 306

    创建自定义界面扩展Window并将您的自定义属性添加为可选 .

    然后,让customWindow使用自定义界面,但与原始窗口一起使用 .

    它与typescript@3.1.3一起使用 .

    interface ICustomWindow extends Window {
      MyNamespace?: any
    }
    
    const customWindow:ICustomWindow = window;
    
    customWindow.MyNamespace = customWindow.MyNamespace {}
    
  • 315

    如果需要使用需要使用 import 的自定义类型扩展 window 对象,可以使用以下方法:

    window.d.ts

    import MyInterface from './MyInterface';
    
    declare global {
        interface Window {
            propName: MyInterface
        }
    }
    

    请参阅本手册'Declaration Merging'部分中的'Global Augmentation':https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

相关问题