2017-04-26 19 views
1

javascriptを拡張してカスタムタイプチェックを追加したいと思います。JavaScriptの構文を拡張してタイピングを追加する

にコンパイルう
function test(welcome:string, num:integer:non-zero) { 
    console.log(welcome + num) 
} 

:これを行うための最も簡単な方法は何

function test(welcome, num) { 
    if(Object.prototype.toString.call(welcome) !== "[object String]") { 
     throw new Error('welcome must be a string') 
    } 

    if (!Number.isInteger(num)) { 
     throw new Error('num must be an integer') 
    } 

    console.log(welcome + num) 
} 

これまでのところ、私が見てきた:

  • sweet.js(私はそれが内部の書き換えのいくつかの並べ替えを通過すると思うとオンラインドキュメントが古く見えます)
  • esprimaとescodegen(わかりません
  • はすべて手動でさまざまなオプションを評価した後、通常のexpressons
+1

タイスクリプトと考えましたか? –

+0

あなたの最後の「提案」はあなたを遠くに連れてこないでしょう。あなたは深刻な "ハッキング"(私はそれがjsの文化と呼ぶものだと思う)をしているので、恐ろしいAPIと古い文書があなたを恐れるべきではありません:) –

+0

@AndyLambはい私は、しかし、より強力で表現力豊かです。たとえば、function(allWages:array [integer:not-negative]:no-empty)...そして、アプリケーションごとにカスタムチェッカーを持つこともできます。 –

答えて

1

を使用して解析する)を開始し、sweet.jsを使用する最善の解決策であるように思われます。まだ仕事をするのはかなり難しいです(私はおそらく間違ったやり方をしています)が、誰かが似たようなことをやりたいのであれば、ここで私の解決策でした。

'use strict' 

    syntax function = function(ctx) { 
     let funcName = ctx.next().value; 
     let funcParams = ctx.next().value; 
     let funcBody = ctx.next().value; 

     //produce the normal params array 
     var normalParams = produceNormalParams(funcParams) 

     //produce the checks 
     var paramChecks = produceParamChecks(funcParams) 

     //produce the original funcBody code 

     //put them together as the final result 

     var params = ctx.contextify(funcParams) 

     var paramsArray = [] 
     for (let stx of params) { 
      paramsArray.push(stx) 
     } 

     var inner = #`` 
     var innerStuff = ctx.contextify(funcBody) 
     for (let item of innerStuff) { 
      inner = inner.concat(#`${item}`) 
     } 

     var result = #`function ${funcName} ${normalParams} { 
      ${paramChecks} 
      ${inner} 
     }` 

     return result 

     function extractParamsAndParamChecks(paramsToken) { 
      var paramsContext = ctx.contextify(paramsToken) 

      //extracts the actual parameters 
      var paramsArray = [] 
      var i = 0; 
      var firstItembyComma = true 
      for (let paramItem of paramsContext) { 
       if (firstItembyComma) { 
        paramsArray.push({ 
         param: paramItem, 
         checks: [] 
        }) 
        firstItembyComma = false 
       } 

       if (paramItem.value.token.value === ',') { 
        firstItembyComma = true 
        i++ 
       } else { 
        paramsArray[i].checks.push(paramItem.value.token.value) 
       } 
      } 

      for (var i = 0; i < paramsArray.length; i++) { 
       var checks = paramsArray[i].checks.join('').split(':') 
       checks.splice(0, 1) 
       paramsArray[i].checks = checks 
      } 

      return paramsArray 
     } 

     function produceNormalParams(paramsToken) { 
      var paramsArray = extractParamsAndParamChecks(paramsToken) 

      //Produces the final params #string 
      var inner = #`` 
      var first = true 
      for (let item of paramsArray) { 
       if (first === true) { 
        inner = inner.concat(#`${item.param}`) 
       } else { 
        inner = inner.concat(#`,${item.param}`) 
       } 
      } 
      return #`(${inner})` 
     } 

     function produceParamChecks(paramsToken) { 
      var paramsArray = extractParamsAndParamChecks(paramsToken) 

      var result = #`` 
      for (let paramObject of paramsArray) { 
       var tests = produceChecks(paramObject) 
       result = result.concat(#`${tests}`) 
      } 
      return result 
     } 

     function produceChecks(paramObject) { 
      var paramToken = paramObject.param 
      var itemType = paramObject.checks[0] 
      var checks  = paramObject.checks 

      if (itemType === undefined) return #`` 

      if (itemType === 'array') { 
       return #`if (Object.prototype.toString.call(${paramToken}) !== "[object Array]") throw new Error('Must be array:' + ${paramToken})` 
      else { 
       throw new Error('item type not recognised: ' + itemType) 
      } 
     } 
    } 
関連する問題