代码之家  ›  专栏  ›  技术社区  ›  olivierr91

如何在TypeScript中定义全局函数?

  •  31
  • olivierr91  · 技术社区  · 7 年前

    我想定义一个在任何地方都可用的全局函数,在使用时不需要导入模块。

    此功能旨在取代安全导航操作员(?)C#版本。为了可读性,我不想在函数前面加模块名。

    全球的d、 ts:

    declare function s<T>(someObject: T | null | undefined, defaultValue?: T | null | undefined) : T;
    

    全球的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;
    }
    

    应用程序。tsx(根TypeScript文件):

    import 'Global';
    

    其他TSX文件(方法用法):

    s(s(nullableVar).member).member; //Runtime error
    

    但是,在浏览器中,这可以很好地编译 s is not a function '.

    3 回复  |  直到 7 年前
        1
  •  31
  •   caseyWebb    7 年前

    您正在为编译器定义类型,但实际上并没有将其附加到全局命名空间 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;
    }
    
        2
  •  12
  •   kanji    6 年前

    感谢@Romain Deneau。他的回答对我有用。 这是我的简化版,让它看起来更容易理解他的答案。 (我的假设脚本在浏览器上运行。此外,我省略了函数的签名 s .)

    在任何类之外定义函数。

    function s() {
        console.log("invoked s()!");
    }
    
    (window as any).s = s;
    

    使用此全局函数 s 从TypeScript类如下;

    declare var s;
    
    export class MyClass {
        public static callFunctionS() {
            s();
        }
    }
    
        3
  •  9
  •   Romain Deneau    7 年前

    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节点测试:

    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);
        });
    });