Help us understand the problem. What is going on with this article?

TypeScriptのimport指定方法

More than 5 years have passed since last update.

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のオプションを付加する。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away