2016-07-12 9 views
2

エラーを表すためにtypescriptインターフェイスを定義します。これは次のようなものです:AMDを使用している場合、d.tsファイルのTypescript列挙型を参照する方法は?

enum MessageLevel { 
    Unknown, 
    Fatal, 
    Critical, 
    Error, 
    Warning, 
    Info, 
    Debug 
} 

interface IMyMessage { 
    name: string; 
    level: MessageLevel; 
    message: string; 
} 

これは問題なく動作します。しかし、今は(おそらく)私はそのインターフェイスを.d.tsファイルで宣言して、他の人がそれを入力に使用できるようにしたいと思っています。しかし、単純な型情報ではなく実装であるため、.d.tsファイルに列挙型を定義したくありません。列挙型は、おそらくのは、それを呼びましょう、.TSファイルである必要がありmessageLevel.ts:

///<amd-module name='MessageLevel'/> 

export enum MessageLevel { 
    Unknown, 
    Fatal, 
    Critical, 
    Error, 
    Warning, 
    Info, 
    Debug 
} 

と私、この時点では、ファイルを入力して、私のd.tsでそれを使用することができますこの方法:

import * as ml from "./MessageLevel"; 

interface IMyMessage { 
    name: string; 
    level: ml.MessageLevel; 
    message: string; 
} 

この作業を行うことはできますが、実装ファイルを入力ファイルにインポートする際のレベルミキシングが嫌いです。実際にタイピングファイルに列挙型を実装するというアイデアも嫌いです。

実装と宣言を厳密に分離しておくために、これを行うためのきれいな方法がありますか?

答えて

4

最良の解決策は、実際のJavaScript変数が数字、文字列、またはそれ以外のものであるかどうかによって異なります。あなたは文字列を気にしない場合、あなたはこのようにそれを行うことができます。

///messagelevel.d.ts 
export type MessageLevel = "Unknown" | "Fatal" | "Critical" | "Error"; 



///main.d.ts 
import * as ml from "./MessageLevel"; 

interface IMyMessage { 
    name: string; 
    level: ml.MessageLevel; 
    message: string; 
} 

をので最後のJavaScriptで、それは単に文字列として表現されますが、活字体は、フラグエラーいつでもあなたが値と比較しますそのリストにないか、別の文字列に割り当てようとします。これはJavaScript自体が何らかの列挙型に最も近いので(document.createElement("video")ではなく、document.createElement(ElementTypes.VIDEO))、このロジックを表現する良い方法の1つかもしれません。

+0

本当にありがとうございます....しかし、私の質問の真のポイントは、仮想列挙型を文字列として、数値として、または型として格納するかどうかではなく、型指定ファイルから列挙型の実装を保持する方法です。 TypeScriptの精神に反して、どんな点でもタイピングファイルをインポートするようです。もしAMDを扱っているのであれば、二重に邪魔になるかもしれません。 –

+0

@StephanGolux上記のサンプルには実際の実装*コードはありません。どちらのサンプルも.d.tsファイルです。 1つの型指定ファイルを参照することは、このシナリオでは非常に一般的で論理的です。つまり、2つのファイルで参照される1つの型( 'enum'、' type'、 'class'など)が必要です。あなたが意図していることを理解しようとすると、これを擬似コードでどのように表示するかの例を教えてください(TypeScriptがそれをコンパイルするかどうかは無視してください)。 – Katana314

+0

@ Katana314。明らかに、私が基本的な概念レベルで欠けているものがあります。私は.tsファイルに列挙型を実装したいと思います。おそらく "export enum MyEnum {...}"を使用して、他の.tsファイルでその実装をインポートすることができます。プロパティを、その列挙型としてタイプされる.d.tsファイル内のインターフェイスの.tsファイルから.d.tsファイルにインポートするのが適切ではないと思います。 –

1

私はこの問題について最後の数日間考えていました、そしておそらく労働組合の種類と相まってconst enumは、適切な選択肢かもしれません。

このアプローチは、あなたのAPIクライアントがが明示的にあなたのAPIファイルにを宣言されていないいくつか列挙型を期待することができるという事実に依存します。

これを考慮します。まず、APIファイルapi.d.ts

/** 
* @file api.d.ts 
* 
* Here you define your public interface, to be 
* implemented by one or more modules. 
*/ 


/** 
* An example enum. 
* 
* The enum here is `const` so that any reference to its 
* elements are inlined, thereby guaranteeing that none of 
* its members are computed, and that no corresponding 
* JavaScript code is emmitted by the compiler for this 
* type definition file. 
* 
* Note how this enum is named distinctly from its 
* "conceptual" implementation, `MyEnum`. 
* TypeScript only allows namespace merging for enums 
* in the case where all namespaces are declared in the 
* same file. Because of that, we cannot augment an enum's 
* namespace across different source files (including 
* `.d.ts` files). 
*/ 
export const enum IMyEnum { A } 

/** 
* An example interface. 
*/ 
export interface MyInterface { 

    /** 
    * An example method. 
    * 
    * The method itself receives `IMyEnum` only. Unfortunately, 
    * there's no way I'm aware of that would allow a forward 
    * declaration of `MyEnum`, like one would do in e.g. C++ 
    * (e.g. declaration vs definition, ODR). 
    */ 
    myMethod(option: IMyEnum): void; 
} 

そしてAPIの実装、impl.ts

/** 
* @file impl.ts 
*/ 

/** 
* A runtime "conceptual" implementation for `IMyEnum`. 
*/ 
enum MyEnum { 
    // We need to redeclare every member of `IMyEnum` 
    // in `MyEnum`, so that the values for each equally named 
    // element in both enums are the same. 
    // TypeScript will emit something that is accessible at 
    // runtime, for example: 
    // 
    // MyEnum[MyEnum["A"] = 100] = "A"; 
    // 
    A = IMyEnum.A 
} 

class MyObject implements IMyInterface { 

    // Notice how this union-typed argument still matches its 
    // counterpart in `IMyInterface.myMethod`. 
    myMethod(option: MyEnum | IMyEnum): void { 
     console.log("You selected: " + MyEnum[option]); 
    } 
} 

// ---- 

var o = new MyObject(); 
o.myMethod(MyEnum.A); // ==> You selected: 100 
o.myMethod(IMyEnum.A); // ==> You selected: 100 

// YAY! (But all this work shouldn't really be necessary, if TypeScript 
// was a bit more reasonable regarding enums and type declaration files...) 

I made this gist as an example、誰かがアクションで、このアプローチを見たい場合には

関連する問題