LoginSignup
9
10

More than 5 years have passed since last update.

TypeScriptのimport指定方法

Last updated at Posted at 2013-10-01

TypeScriptで作成した State Monadをモジュールにしてみた。
importの指定に、若干迷いましたので共有します。

今回の目標

TypeScriptのモジュール化を行う。

モジュールの配置

State Monadモジュールは、ファイル名stateMonad.tsとし、root/monad/state/stateMonad.tsに配置する。
Stackモジュールは、ファイル名stack.tsとし、root/stack/stack.tsに配置する。
テストモジュールは、ファイル名stackTest.tsとし、root/stackTest.tsに配置する。

State Monadモジュール

root/monad/state/stateMonad.ts
export
  module monad.state {
    export 
      interface Tuple2<A,B> {
        fst: A
        snd: B
      }
    export
      class State<T,X>{
        runState: (t:T) => Tuple2<X,T>
        evalState = (t:T):X => this.runState(t).fst
        execState = (t:T):T => this.runState(t).snd
        constructor(g:(t:T) => Tuple2<X,T>){
          this.runState = g
        }
        static returns<T,X>(v:X):State<T,X>{
          return new State<T,X>((t:T) => { return {fst:v, snd:t } })
        } 
        bind<B>(f: (x:X) => State<T,B>):State<T,B>{
          var g = (t:T) => {
            var st = this.runState(t)
            return f(st.fst).runState(st.snd)
          }
          return new State<T,B>(g)
        }
      }
    export
      class MonadState {
        static get<T>():State<T,T> {
          var g = (t:T) => {
            return { fst: t, snd: t }
          }
          return new State<T,T>(g)
        }
        static put<T>(a:T):State<T,void> {
          var g = (t:T) => {
            return { fst: null,  snd: a }
          }
          return new State<T,void>(g)
        }
      }
}

モジュールとして外部に提供するmoduleclassにはexportを付加した。
Tuple2は本来なら別モジュールとするべきだが、今回はこのモジュールに含めた。

Stackモジュール

root/stack/stack.ts
import ms = require("../monad/state/stateMonad")
export
  module stack {
    export 
      class Stack<X> {
        pop = <X>():ms.monad.state.State<X,X[]> =>
          ms.monad.state.MonadState.get<X[]>()
            .bind((e:X[]) => { 
                 return ms.monad.state.MonadState.put<X[]>(e.slice(1))
                             .bind(k => ms.monad.state.State.returns(e[0])) })

        push = <X>(i:X):ms.monad.state.State<X,void> =>
          ms.monad.state.MonadState.get<X[]>()
            .bind((e:X[]) => 
                 ms.monad.state.MonadState.put<X[]>([i].concat(e)))
      }
  }

外部モジュールのstateMonad.tsを使用するため、importが必要。
requireはこのモジュールからの相対パスを指定する。
また、外部モジュールを使用する際は、importに使用したms.にフォルダ名monad.state.を付加して使用する。

テストモジュール

root/stackTest.ts
import ms = require("./monad/state/stateMonad")
import st = require("./stack/stack")

var fnc = <X>(st:st.stack.Stack):ms.monad.state.State<X,X[]> =>
  st.pop()
    .bind(e => st.pop())
    .bind(e => st.push(20))
    .bind(e => st.pop())
    .bind(e => st.push(e*5))

console.log(fnc(new st.stack.Stack<number>()).execState([1,2,3])) //=> [100,3]

外部モジュールのstateMonad.tsstack.tsimportが必要。
ここでも相対パスを指定する。

コンパイル

コンパイルする際は、--module commonjsのオプションを付加する。
Webで見ると--module amdでも良いと書いてあるが、私の環境では実行時にエラーとなった。
rootに移動し、コンパイルコマンドを発行する。

/root
ts stateTest.ts --module commonjs

実行

rootに移動し、node.jsにて実行する。

/root
node stateTest.js // [100,3]

期待した値が表示された。

まとめ

以前importに指定していたmoduleがdeprecatedになっているため、requireを使用する。
requireには相対パスを指定する(別の方法があるかもしれません)。
外部クラスを使用する場合は、importに使用した変数(今回の場合はms)と、フォルダ階層を.で区切り指定する。
コンパイル時には、--module commonjsのオプションを付加する。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10