関数パラメーターのタイプを設定しますか?


161

特定のパラメーターが特定のタイプであることをJavaScript関数に知らせる方法はありますか?

このようなことをすることができれば完璧です:

function myFunction(Date myDate, String myString)
{
    //do stuff
}

ありがとうございました!

更新:答えはかなり「いいえ」myDateであるため、日付として扱われる場合は(日付関数を呼び出すために)、関数内で日付としてキャストするか、新しい変数を設定する必要がありますそれに日付を入力?


1
組み込みの一般的な意味ではありません。これは手動で手動で実行できますが、「特定のタイプの」定義方法に依存します
hugomg

2
JavaScriptにはクラスもないため、はありませDateobject
取り除く


@dmr、それはクラスではありません。Date関数です。見てみましょうstackoverflow.com/questions/1646698/... JavaScriptの詳細を見つけるためにnewキーワードを。また、クラスがないため、キャストはありません。必要な関数を呼び出すだけです。オブジェクトにそれらが含まれている場合は実行され、そうでない場合はエラーが発生します。
取り除く

2
それは古いものですが、typescriptについて誰も言及していませんでした
キット

回答:


180

いいえ、JavaScriptは静的に型付けされた言語ではありません。関数本体のパラメーターの型を手動で確認する必要がある場合があります。


180
祝福と呪い。
Jeffrey Sweeney

40
@JeffreySweeneyはどちらもPHPが静的に型付けされています。しかし、phpで型ヒントを実行するオプションがあります。大きな nodejsバックエンドアプリケーションを見たことがありますか?正確には、各関数には引数があり、各引数が何であるかはわかりません。私たちは何千もの引数について話しているので、読むときは、コード全体、および呼び出し元とその呼び出し元のコード全体などを読む必要があります。あなたは確かに冗談を言う必要があります。
Toskan

14
タイプヒンティングを許可する機能を呼び出さない人をバッシングする以外は、typescriptを指摘したいと思うかもしれません:typescriptlang.org基本的にEM6 +タイプヒンティング
Toskan

23
@JeffreySweeneyそれは祝福ではありません。それは癌です。
Robo Robok

1
@Toskan私はそれが祝福ではないとは言いません。私はJavaScriptを4年間使用していますが、それは一部の言語の性質にすぎません。プログラミング言語のセットがなければならない、弱く強く、それがローレベルからハイレベルまでの範囲でなければならないのと同じ方法を入力する入力した範囲です。さらに、JavaScriptはこれを支援するためのinstanceofおよびtypeofキーワードを提供します。これはより多くのコードを必要としますが、タイプに大きく依存するものの言語としてJavaScriptを選択するのは開発者の責任です。巨大なnodejsバックエンドアプリケーションについては?それは常識だと思います。
Marvin

81

JavaScript自体ではなく、Google Closure Compilerの拡張モードを使用すると、次のことができます。

/**
 * @param {Date} myDate The date
 * @param {string} myString The string
 */
function myFunction(myDate, myString)
{
    //do stuff
}

http://code.google.com/closure/compiler/docs/js-for-compiler.htmlを参照してください


1
これは、Eclipse JavaScriptエディターアウトラインビューコード補完)でも機能します。foo( /*MyType*/ param )ここで説明されている方法も機能しますが、stackoverflow.com
Andreas Dietrich

私はこの質問がどれほど古いかを理解していますが、IntelliJでそれが認められていることを指摘したいと思います。ここで非常に過小評価された答え。
ChettDM

67

JavaScript に言語について型について通知することはできませんが、IDEに対して型について通知することができるため、より便利なオートコンプリートが得られます。

これを行うには2つの方法があります。

  1. JavaScriptコードをコメントに文書化するシステムであるJSDocを使用します。特に、@paramディレクティブが必要になります:

    /**
     * @param {Date} myDate - The date
     * @param {string} myString - The string
     */
    function myFunction(myDate, myString) {
      // ...
    }

    JSDocを使用してカスタムタイプ定義し@param、それらをディレクティブで指定することもできますが、JSDocはタイプチェックを実行しないことに注意してください。これは単なるドキュメントツールです。JSDocで定義されているタイプを確認するには、JSScriptタグ解析できるTypeScriptを調べます

  2. のパラメータの直前にタイプを指定して、タイプヒントを使用します
    /* comment */

    WebStormでのJavaScriptタイプのヒント

    これはかなり広く使わている手法で、たとえばReactJSで使用さています。サードパーティのライブラリに渡されるコールバックのパラメータに非常に便利です。

TypeScript

実際の型チェックの最も近い解決策は、JavaScriptの(ほとんど)スーパーセットであるTypeScriptを使用することです。ここだ活字体は、5分で


8
これを入手する方法はVSCode
Anand Undavia

2
ありがとう。これはIDEに依存しますが。VIを使用していますが、機能しません。
negrotico19

@ negrotico19:vi過度に乱用されたエディターであり、IDEではありません。Excelでミュージックビデオをvi作成できるのと同じように、多くのことができます。良いアイデア?おそらく違います。ジョブに適したツールを使用します。
Dan Dascalescu

23

Facebookの新しいフローライブラリ「JavaScriptプログラムで型エラーを見つけるように設計された静的型チェッカー」をチェックしてください。

定義:

/* @flow */
function foo(x: string, y: number): string {
  return x.length * y;
}
foo('Hello', 42);

タイプチェック:

$> flow
hello.js:3:10,21: number
This type is incompatible with
  hello.js:2:37,42: string

そして、ここでそれを実行する方法です。


xが日付型の場合、型定義を追加する方法 つまり、foo(x:日付):文字列{}。これは正しい方法ですか?
Aakash Sigdel

12

いいえ、代わりに、ニーズに応じて次のようなことを行う必要があります。

function myFunction(myDate, myString) {
  if(arguments.length > 1 && typeof(Date.parse(myDate)) == "number" && typeof(myString) == "string") {
    //Code here
  }
}

12

関数のラッパーを使用して、型チェックを自動的に処理するシステムを実装できます。

このアプローチでdeclarative type check systemは、型チェックを管理するコンプリートを構築できます。この概念をさらに詳しく見てみたい場合は、Functypedライブラリを確認してください。

次の実装は、主なアイデアを単純化した、しかし有効な方法で示しています。

/*
 * checkType() : Test the type of the value. If succeds return true, 
 * if fails, throw an Error
 */
function checkType(value,type, i){
  // perform the appropiate test to the passed 
  // value according to the provided type
  switch(type){
    case Boolean : 
      if(typeof value === 'boolean') return true;
      break;
    case String : 
      if(typeof value === 'string') return true;
      break;
    case Number : 
      if(typeof value === 'number') return true;
      break;
    default :
      throw new Error(`TypeError : Unknown type provided in argument ${i+1}`);
  }
  // test didn't succeed , throw error
  throw new Error(`TypeError : Expecting a ${type.name} in argument ${i+1}`);
}


/*
 * typedFunction() : Constructor that returns a wrapper
 * to handle each function call, performing automatic 
 * arguments type checking
 */
function typedFunction( parameterTypes, func ){
  // types definitions and function parameters 
  // count must match
  if(parameterTypes.length !== func.length) throw new Error(`Function has ${func.length} arguments, but type definition has ${parameterTypes.length}`);
  // return the wrapper...
  return function(...args){
    // provided arguments count must match types
    // definitions count
    if(parameterTypes.length !== args.length) throw new Error(`Function expects ${func.length} arguments, instead ${args.length} found.`);
    // iterate each argument value, and perform a
    // type check against it, using the type definitions
    // provided in the construction stage
    for(let i=0; i<args.length;i++) checkType( args[i], parameterTypes[i] , i)
    // if no error has been thrown, type check succeed
    // execute function!
    return func(...args);
  }
}

// Play time! 
// Declare a function that expects 2 Numbers
let myFunc = typedFunction( [ Number, Number ],  (a,b)=>{
  return a+b;
});

// call the function, with an invalid second argument
myFunc(123, '456')
// ERROR! Uncaught Error: TypeError : Expecting a Number in argument 2


11

編集:7年後、この答えはまだ時折賛成票を獲得しています。ランタイムチェックを探している場合は問題ありませんが、Typescript、または場合によってはFlowを使用したコンパイル時のタイプチェックをお勧めします。詳細については、上記のhttps://stackoverflow.com/a/31420719/610585を参照してください

元の答え:

言語に組み込まれていませんが、ご自分で簡単に行うことができます。Vibhuの答えは、Javascriptでの型チェックの典型的な方法と私が考えるものです。より一般的なものが必要な場合は、次のように試してください:(開始するための単なる例)

typedFunction = function(paramsList, f){
    //optionally, ensure that typedFunction is being called properly  -- here's a start:
    if (!(paramsList instanceof Array)) throw Error('invalid argument: paramsList must be an array');

    //the type-checked function
    return function(){
        for(var i=0,p,arg;p=paramsList[i],arg=arguments[i],i<paramsList.length; i++){
            if (typeof p === 'string'){
                if (typeof arg !== p) throw new Error('expected type ' + p + ', got ' + typeof arg);
            }
            else { //function
                if (!(arg instanceof p)) throw new Error('expected type ' + String(p).replace(/\s*\{.*/, '') + ', got ' + typeof arg);
            }
        }
        //type checking passed; call the function itself
        return f.apply(this, arguments);
    }
}

//usage:
var ds = typedFunction([Date, 'string'], function(d, s){
    console.log(d.toDateString(), s.substr(0));
});

ds('notadate', 'test');
//Error: expected type function Date(), got string
ds();
//Error: expected type function Date(), got undefined
ds(new Date(), 42);
//Error: expected type string, got number
ds(new Date(), 'success');
//Fri Jun 14 2013 success

5

それはeasillyで行うことができますArgueJS

function myFunction ()
{
  arguments = __({myDate: Date, myString: String});
  // do stuff
};

2
素晴らしいライブラリのように見えます。おめでとうございます。
FRD

1

typeofまたはを使用instanceof

const assert = require('assert');

function myFunction(Date myDate, String myString)
{
    assert( typeof(myString) === 'string',  'Error message about incorrect arg type');
    assert( myDate instanceof Date,         'Error message about incorrect arg type');
}

0

多分このようなヘルパー関数。ただし、このような構文を定期的に使用している場合は、おそらくTypescriptに切り替える必要があります。

function check(caller_args, ...types) {
    if(!types.every((type, index) => {
        if(typeof type === 'string')
            return typeof caller_args[index] === type
        return caller_args[index] instanceof type;
    })) throw Error("Illegal argument given");
}

function abc(name, id, bla) {
   check(arguments, "string", "number", MyClass)
   // code
}

0

私もこれについて考えてきました。Cのバックグラウンドから、次のようなものを使用して、パラメーターのタイプだけでなく、関数の戻りコードのタイプをシミュレートできます。

function top_function() {
    var rc;
    console.log("1st call");
    rc = Number(test_function("number", 1, "string", "my string"));
    console.log("typeof rc: " + typeof rc + "   rc: " + rc);
    console.log("2nd call");
    rc = Number(test_function("number", "a", "string", "my string"));
    console.log("typeof rc: " + typeof rc + "   rc: " + rc);
}
function test_function(parm_type_1, parm_val_1, parm_type_2, parm_val_2) {
    if (typeof parm_val_1 !== parm_type_1) console.log("Parm 1 not correct type");
    if (typeof parm_val_2 !== parm_type_2) console.log("Parm 2 not correct type");
    return parm_val_1;
}

2番目の呼び出しでtypeof rc = numberであるが値がNaNである2回目の呼び出しに見られるように、呼び出し関数の前のNumberは、返される実際の値のタイプに関係なくNumberタイプを返します

上記のconsole.logは次のとおりです。

1st call
typeof rc: number   rc: 1
2nd call
Parm 1 not correct type
typeof rc: number   rc: NaN

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.