2017-12-10 11 views
3

モジュールを使用するときにインポートする必要なく、どこでも使用できるグローバル関数を定義したいと思います。TypeScriptでグローバル関数を定義する方法は?

この関数は、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(ルートtypescriptファイル):

import 'Global'; 

他TSXファイル(メソッドの使用):

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

これはうまくコンパイルされますが、ブラウザで 's is not a function'がスローされます。

答えて

3

コンパイラのタイプを定義していますが、実際にはグローバルネームスペースに接続しません。つまり、ブラウザの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を使用して、同じファイルで型を宣言することができ、例えば...のようなものを使用exportキーワードを削除し、グローバルオブジェクトを強化するためにいくつかのコードを追加します。ほんの少しの微調整

// 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; 
} 
+0

は、私はプロパティ 's' は型「Window''上に存在しない '得ます。 2番目の解決策では、 'グローバルスコープの拡張は、外部モジュールまたは周囲モジュール宣言に直接入れ子にすることしかできません。 ' – sixtstorm1

+0

私はdtsファイルの関数を 'declare global {...}'の中にラップしようとしましたが、関数を使用するとコンパイル時にエラー ''名前を見つけることができません '私は欲しくない。 – sixtstorm1

+0

私は自分の答えを編集しました。うまくいけば助けてくれます。 – CaseyWebb

1

global.ts(x)ニーズは、有効な「グローバルモジュール」(唯一の副作用でモジュール)されるように。同じファイルにグローバル宣言を指定し、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';。モカ、チャイ、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); 
    }); 
}); 
+0

これは私がCaseeyWebbの答えに基づいて行ったことです。ありがとうございます – sixtstorm1

+0

@ sixtstorm1:nice!それは完全に有効な答えなので、有用ではあるが完了していない回答ではなく、次のリーダーを優先的にリダイレクトするために、それをマークしてください(または少なくとも「+」を追加してください)? –

+0

はい私はあなたの答えをupvotedしました。 – sixtstorm1

関連する問題