我想定义一个可在任何地方使用的全局函数,而无需在使用时导入模块。
此功能旨在替换C#中提供的安全导航操作符(?)。为了便于阅读,我不想在函数前加上模块名称。
Global.d.ts:
declare function s<T>(someObject: T | null | undefined, defaultValue?: T | null | undefined) : T;
Global.tsx:
///<reference path="Global.d.ts" />
export function s<T>(object: T | null | undefined, defaultValue: T | null = null = {} as T) : T {
if (typeof object === 'undefined' || object === null)
return defaultValue as T;
else
return object;
}
App.tsx(root TypeScript文件):
import 'Global';
其他TSX文件(方法用法):
s(s(nullableVar).member).member; //Runtime error
这个编译得很好,但是,在浏览器中这会抛出&#39; s is not a function
&#39;。
答案 0 :(得分:12)
您正在定义编译器的类型,但实际上并未将其附加到全局命名空间 - 浏览器中的window
,节点中的global
。不要从模块中导出它,而是附加它。对于同构使用,请使用类似......
function s() { ... }
// must cast as any to set property on window
const _global = (window /* browser */ || global /* node */) as any
_global.s = s
您也可以放弃.d.ts
文件并使用declare global
在同一文件中声明类型,例如
// we must force tsc to interpret this file as a module, resolves
// "Augmentations for the global scope can only be directly nested in external modules or ambient module declarations."
// error
export {}
declare global {
function s<T>(someObject: T | null | undefined, defaultValue?: T | null | undefined) : T;
}
const _global = (window /* browser */ || global /* node */) as any
_global.s = function<T>(object: T | null | undefined, defaultValue: T | null = null) : T {
if (typeof object === 'undefined' || object === null)
return defaultValue as T;
else
return object;
}
答案 1 :(得分:4)
global.ts(x)
只需稍微调整即可成为有效的“全局模块”(仅限副作用的模块):删除export
关键字并添加一些代码增强全球对象。您还可以在同一文件中提供全局声明,然后删除global.d.ts
。
function _s<T>(object: T | null, defaultValue: T = {} as T) : T {
return object == null
? defaultValue
: object as T;
}
// Global declaration
declare var s: typeof _s;
// Global scope augmentation
var window = window || null;
const _global = (window || global) as any;
_global.s = _s;
要使用它,只需导入一次模块,例如在App.tsx
中通过全局导入导入:import './global';
。
使用mocha,chai,ts-node测试:
import { expect } from 'chai';
import './global'; // To do once at app bootstrapping
describe('global s()', () => {
it('should replace null with empty object', () => {
const result = s(null);
expect(result).to.eql({});
});
it('should replace undefined with empty object', () => {
const result = s(undefined);
expect(result).to.eql({});
});
it('should replace null with the given default value', () => {
const defVal = { def: 'val' };
const result = s(null, defVal);
expect(result).to.eql({ def: 'val' });
});
it('should preserve defined object', () => {
const object = { bar: 'a' };
const result = s(object);
expect(result).to.eql(object);
});
});
答案 2 :(得分:1)
感谢@Romain Deneau。他的回答对我有用。
这是我的简化版本,使您更容易理解他的答案。
(我的脚本假定脚本在浏览器上运行。此外,我省略了函数s
的签名。)
在任何类之外定义函数。
function s() {
console.log("invoked s()!");
}
(window as any).s = s;
使用TypeScript类中的此全局函数s
如下所示;
declare var s;
export class MyClass {
public static callFunctionS() {
s();
}
}