在JavaScript中,我可以这样做:
something = 'testing';
然后在另一个文件中:
if (something === 'testing')
并且将定义something
(只要它们以正确的顺序被调用)。
我似乎无法弄清楚如何在TypeScript中做到这一点。
这是我尝试过的。
在.d.ts文件中:
interface Window { something: string; }
然后在我的main.ts文件中:
window.something = 'testing';
然后在另一个文件中:
if (window.something === 'testing')
这很有效。但是我希望能够丢失它的window.
部分,让我的something
成为全球性的。有没有办法在TypeScript中做到这一点?
(如果有人感兴趣,我真的想为我的应用程序设置日志记录。我希望能够从任何文件中调用log.Debug
而无需导入和创建对象。)
答案 0 :(得分:36)
在.d.ts
定义文件
type MyGlobalFunctionType = (name: string) => void
如果您在浏览器中工作, 您将成员添加到浏览器的窗口上下文中:
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");
答案 1 :(得分:11)
如果我将JavaScript与TypeScript结合使用,我找到了一种方法。
logging.d.ts:
private function buildMenu($menu, $depth = 0, $nestingUL = true, $showElementOverride = false) {
$ulNode = $this->doc->createElement('ul');
if (!$depth) {
$ulNode->setAttribute('id', 'primary-nav');
$this->rootNode = $ulNode;
}
$this->appendtoNode($menu, $depth, $nestingUL, $ulNode, $showElementOverride);
return $ulNode;
}
private function appendtoNode($menu, $depth, $nestingUL, $node, $showElementOverride = false) {
foreach ($menu as $itemText => $item) {
if (empty($item['hide']) || !($item['hide']) || $showElementOverride) {
$node->appendChild($this->buildMenuItem($itemText, $item, $depth, $nestingUL));
}
else if ((array_key_exists('hide', $item) && $item['hide']) && !$nestingUL) {
$tempMenu = $this->hiddenArraySkipNext($item);
if (is_array($tempMenu)) $this->appendtoNode($tempMenu, $depth, $nestingUL, $node, $showElementOverride);
}
}
return;
}
private function hiddenArraySkipNext($arr = array()) {
$output = array();
foreach ($arr as $tempArr) {
$output = $tempArr;
if (is_array($tempArr) && !empty($tempArr)) {
foreach ($tempArr as $val) {
if (is_array($val) && array_key_exists('hide', $val) && $val['hide']) {
$this->hiddenArraySkipNext($val);
}
}
}
}
return $output;
}
登录声明的 JS 强>:
declare var log: log4javascript.Logger;
initalize-app.ts
log = null;
这将它放在全局范围内,TypeScript知道它。所以我可以在我的所有文件中使用它。
注意:我认为这只有效,因为我将import './log-declaration.js';
// Call stuff to actually setup log.
// Similar to this:
log = functionToSetupLog();
TypeScript选项设置为true。
如果有人发布纯粹的TypeScript解决方案,我会接受。
答案 2 :(得分:7)
好的,所以你做的事情可能更加丑陋,但无论如何......
但我这样做......
在纯TypeScript中可以做的是使用eval
函数,如下所示:
declare var something: string;
eval("something = 'testing';")
以后你可以做
if (something === 'testing')
这只不过是在没有TypeScript拒绝编译的情况下强制执行指令的黑客攻击,而我们declare var
用于TypeScript编译其余的代码。
答案 3 :(得分:4)
我只使用这个
import {globalVar} from "./globals";
declare let window:any;
window.globalVar = globalVar;
答案 4 :(得分:1)
这是我解决的方法:
步骤:
声明了全局名称空间,例如custom.d.ts如下:
声明全局{ 命名空间NodeJS { 全局{ 配置:{} } } } 导出默认全局;
将上面创建的文件映射到“ tsconfig.json”中,如下所示:
“ typeRoots”:[“ src / types / custom.d.ts”]
在以下任何文件中获取上面创建的全局变量:
console.log(global.config)
注意:
打字稿版本:“ 3.0.1”。
在我的情况下,要求是在启动应用程序之前设置全局变量,并且该变量应访问整个依赖对象,以便我们可以获得所需的配置属性。
希望这会有所帮助!
谢谢
答案 5 :(得分:1)
this link是未来。
// Way 1
var abc: number
globalThis.abc = 200 // no error
// Way2
declare var age: number
globalThis.age = 18 // no error
注意:包含以上代码的文件不能包含任何
import
语句
到目前为止,这些是我想出的扩展全局对象的方法。
所有魔法都来自var
。将var
替换为let
或const
无效。
我尝试将模块
globalThis
扩展为globalThis,但失败了。
答案 6 :(得分:1)
我花了几个小时来找出正确的方法。就我而言,我正在尝试定义全局“ log”变量,因此步骤如下:
1)将tsconfig.json
配置为包括定义的类型(src/types
文件夹,node_modules-由您决定):
...other stuff...
"paths": {
"*": ["node_modules/*", "src/types/*"]
}
2)创建具有以下内容的文件src/types/global.d.ts
(不导入!-这很重要),可以随时更改any
以满足您的需要并使用{{1 }}界面,而不是window
(如果您使用的是浏览器):
NodeJS
3)现在,您终于可以在需要的地方使用/实现/**
* IMPORTANT - do not use imports in this file!
* It will break global definition.
*/
declare namespace NodeJS {
export interface Global {
log: any;
}
}
declare var log: any;
:
log
答案 7 :(得分:1)
我需要使lodash全局化,以使用仅需要的,无法更改的现有.js文件。
我发现这可行:
import * as lodash from 'lodash';
(global as any)._ = lodash;
答案 8 :(得分:1)
使用更具体的示例(仅使用 TypeScript,不与 JavaScript 混合)扩展关于 globalThis
(参见 MDN 和 TypeScript 3.4 note)的另一个答案,因为这种行为相当令人困惑。所有示例都在 Nodejs v12.14.1
和 TypeScript Version 4.2.3
下运行。
declare var ENVIRONMENT: string;
globalThis.ENVIRONMENT = 'PROD';
console.log(ENVIRONMENT);
console.log(globalThis.ENVIRONMENT);
// output
// PROD
// PROD
这个文件没有 import
或 export
,所以它是一个全局范围的文件。您可以编译上述 TypeScript 代码而不会出现任何错误。请注意,您必须使用 var
。使用 let
会抛出 error TS2339: Property 'ENVIRONMENT' does not exist on type 'typeof globalThis'.
您可能会注意到,我们declare
对变量进行了处理,而以下同样有效。
var ENVIRONMENT: string;
ENVIRONMENT = 'DEV';
globalThis.ENVIRONMENT = 'PROD';
console.log(ENVIRONMENT);
console.log(globalThis.ENVIRONMENT);
// output
// DEV
// PROD
输出来自 Nodejs v12.14.1
。我还在 Chrome(编译为 JS 后)中对其进行了测试,并且都输出了 PROD
。所以我建议一直使用 globalThis
。
declare var ENVIRONMENT: string;
globalThis.ENVIRONMENT = 'PROD';
export {};
一旦我们添加了export
语句,它就变成了一个模块作用域文件,它抛出error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
,解决办法是augment global scope。
declare global {
var ENVIRONMENT: string;
}
globalThis.ENVIRONMENT = 'PROD';
console.log(globalThis.ENVIRONMENT);
export {};
你仍然必须使用var
,否则你会得到error TS2339: Property 'ENVIRONMENT' does not exist on type 'typeof globalThis'.
。
// ./main.ts
import './environment_prod';
console.log(ENVIRONMENT);
console.log(globalThis.ENVIRONMENT);
// ./environment_prod.ts
declare var ENVIRONMENT: string;
globalThis.ENVIRONMENT = 'PROD';
或
// ./environment_prod.ts
declare global {
var ENVIRONMENT: string;
}
globalThis.ENVIRONMENT = 'PROD';
export {}; // Makes the current file a module.
假设 main.ts
和 environment_prod.ts
都是入口文件。 Browserify 会将它们(编译为 JS 后)包装到需要使用 globalThis
的局部作用域函数中。
// ./main.ts
declare var ENVIRONMENT: string;
console.log(ENVIRONMENT);
console.log(globalThis.ENVIRONMENT);
// ./environment_prod.ts
declare var ENVIRONMENT: string;
globalThis.ENVIRONMENT = 'PROD';
但是共享一个声明文件更类型安全,然后两个入口文件都可以导入该声明文件,以避免变量名称或类型名称的拼写错误。
// ./main.ts
import './environment';
console.log(ENVIRONMENT);
console.log(globalThis.ENVIRONMENT);
// ./environment_prod.ts
import './environment';
globalThis.ENVIRONMENT = 'PROD';
// ./environment.ts
type Environment = 'PROD' | 'DEV' | 'LOCAL';
declare var ENVIRONMENT: Environment;
注意顺序很重要:browserify environment_prod.js main.js > bin.js
答案 9 :(得分:0)
作为Dima V答案的补充,这就是我为此做的工作。
// First declare the window global outside the class
declare let window: any;
// Inside the required class method
let globVarName = window.globVarName;
答案 10 :(得分:0)
这对我有用,如this thread中所述:
declare let something: string;
something = 'foo';
答案 11 :(得分:0)
我正在使用它:
interface Window {
globalthing: any;
}
declare var globalthing: any;