Set type for function parameters?

后端 未结 12 1785
醉话见心
醉话见心 2020-11-30 18:37

Is there a way to let a javascript function know that a certain parameter is of a certain type?

Being able to do something like this would be perfect:



        
相关标签:
12条回答
  • 2020-11-30 18:55

    You can implement a system that handles the type checks automatically, using a wrapper in your function.

    With this approach, you can build a complete declarative type check system that will manage for you the type checks . If you are interested in taking a more in depth look at this concept, check the Functyped library

    The following implementation illustrates the main idea, in a simplistic, but operative way :

    /*
     * 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

    0 讨论(0)
  • 2020-11-30 18:56

    While you can't inform JavaScript the language about types, you can inform your IDE about them, so you get much more useful autocompletion.

    Here are two ways to do that:

    1. Use JSDoc, a system for documenting JavaScript code in comments. In particular, you'll need the @param directive:

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

      You can also use JSDoc to define custom types and specify those in @param directives, but note that JSDoc won't do any type checking; it's only a documentation tool. To check types defined in JSDoc, look into TypeScript, which can parse JSDoc tags.

    2. Use type hinting by specifying the type right before the parameter in a
      /* comment */:

      JavaScript type hinting in WebStorm

      This is a pretty widespread technique, used by ReactJS for instance. Very handy for parameters of callbacks passed to 3rd party libraries.

    TypeScript

    For actual type checking, the closest solution is to use TypeScript, a (mostly) superset of JavaScript. Here's TypeScript in 5 minutes.

    0 讨论(0)
  • 2020-11-30 19:02

    No, instead you would need to do something like this depending on your needs:

    function myFunction(myDate, myString) {
      if(arguments.length > 1 && typeof(Date.parse(myDate)) == "number" && typeof(myString) == "string") {
        //Code here
      }
    }
    
    0 讨论(0)
  • 2020-11-30 19:02

    TypeScript is one of the best solution for now

    TypeScript extends JavaScript by adding types to the language.

    https://www.typescriptlang.org/

    0 讨论(0)
  • 2020-11-30 19:04

    No, JavaScript is not a statically typed language. Sometimes you may need to manually check types of parameters in your function body.

    0 讨论(0)
  • 2020-11-30 19:04

    Edit: Seven years later, this answer still gets occasional upvotes. It's fine if you are looking for runtime checking, but I would now recommend compile-time type checking using Typescript, or possibly Flow. See https://stackoverflow.com/a/31420719/610585 above for more.

    Original answer:

    It's not built into the language, but you can do it yourself quite easily. Vibhu's answer is what I would consider the typical way of type checking in Javascript. If you want something more generalized, try something like this: (just an example to get you started)

    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
    
    0 讨论(0)
提交回复
热议问题