Встановити тип параметрів функції?


161

Чи є спосіб дозволити функції javascript знати, що певний параметр певного типу?

Бути в змозі зробити щось подібне було б ідеально:

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

Дякую!

Оновлення : Оскільки відповідь є гучним "ні", якщо я хочу myDateтрактуватись як дата (для того, щоб викликати функції дати на ній), я повинен призначити її датою всередині функції або встановити нову змінну введіть дату?


1
Не у вбудованому та загальному сенсі. Ви можете зробити це самостійно, вручну, але тоді це залежить від того, як ви визначаєте "певного типу"
hugomg

2
У JavaScript також немає класів, тому немає Date, тільки object.
позбутися


@dmr, це не клас. Dateє функцією. Погляньте на stackoverflow.com/questions/1646698/…, щоб дізнатися більше про newключове слово JavaScript . Також, оскільки немає занять, немає і кастингу. Ви можете просто зателефонувати потрібним функціям. Якщо об'єкт їх містить, вони запустяться, інакше ви отримаєте помилку.
позбутися

2
Це старий, проте ніхто не згадав машинопис
комплект

Відповіді:


180

Ні, JavaScript не є статично набраною мовою. Іноді може знадобитися вручну перевірити типи параметрів у своєму функціональному тілі.


180
Благословення та прокляття.
Jeffrey Sweeney

40
@JeffreySweeney ні на PHP не набраний статично. Але у вас є можливість ввести підказку в php. Ви коли-небудь переглядали велику програму для створення резервного сервера nodejs? точно, кожна функція має аргументи, і у вас немає поняття, що таке кожен аргумент. Ми говоримо про тисячі аргументів, і, читаючи, ви повинні прочитати весь код і весь код абонента та його абонента тощо. Благословення? ви, безумовно, повинні бути дзижачими.
Тоскан

14
окрім того, що б'є когось, хто не викликає функції, що дозволяє натякати на благо, я можу хотіти вказати на машинопис: typecriptlang.org в основному EM6 +
натяк на

23
@JeffreySweeney Це не благо. Це рак.
Робо Робок

1
@Toskan Я б не сказав, що це не благо. Я використовую JavaScript вже чотири роки, і це лише природа деяких мов. Набір мов програмування повинен варіюватися від слабо набраного до сильно набраного так само, як і від низького до високого рівня. Крім того, JavaScript надає instanceofта typeofключові слова, які допоможуть у цьому. Хоча це займає більше коду, можливо, саме розробник вибирає JavaScript як мову для чогось, що багато в чому залежить від типів. Що стосується величезних застосунків додатків nodejs? Я думаю, що це має бути здоровий глузд.
Марвін

82

Не в javascript it self, але використовуючи розширений режим 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
це також працює з / вмикає редактор JavaScript Eclipse - перегляд контуру та завершення коду . тоді foo( /*MyType*/ param )як описаний тут спосіб також працює: stackoverflow.com/a/31420719/1915920
Андреас Дітріх

Я розумію, скільки років це питання, але я хотів зазначити, що його заслуговують в IntelliJ. Тут дуже неоцінена відповідь.
ChettDM

67

Поки ви не можете повідомити мову про мову про типи, ви можете повідомити про них свою IDE, так що ви отримаєте набагато корисніше автозавершення.

Ось два способи зробити це:

  1. Використовуйте JSDoc , систему документування коду JavaScript у коментарях. Зокрема, вам знадобиться @paramдиректива :

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

    Ви також можете використовувати JSDoc для визначення користувальницьких типів та вказівки в @paramдирективах, але зауважте, що JSDoc не буде перевіряти тип це лише інструмент документації. Щоб перевірити типи, визначені в JSDoc, подивіться в TypeScript , який може проаналізувати теги JSDoc .

  2. Використовуйте підказку типу, вказавши тип прямо перед параметром у
    /* comment */:

    Підказки типу JavaScript у WebStorm

    Це досить поширена методика, яку застосовує , наприклад, ReactJS . Дуже зручно для параметрів зворотних викликів, переданих стороннім бібліотекам.

TypeScript

Для перевірки фактичного типу найближчим рішенням є використання TypeScript, ( здебільшого ) набору JavaScript. Ось TypeScript за 5 хвилин .


8
Як це зробити VSCode?
Ананд Ундавія

2
Дякую. Хоча це залежить від IDE. Я використовую VI і не працюватиму.
negrotico19

@ negrotico19: viце надмірно зловживаний редактор, а не IDE. Ви можете робити багато речей vi, так само як ви можете робити музичні відео в Excel . Гарна ідея? Напевно, ні. Використовуйте правильний інструмент для роботи.
Дан Даскалеску

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: дата): рядок {}. це правильний спосіб зробити це?
Аакаш Зігдел

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

Редагувати: Через сім років ця відповідь все ще отримує певні відгуки. Це добре, якщо ви шукаєте перевірку виконання, але я б зараз рекомендував перевірку типу компіляції за допомогою 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

Це легко зробити з 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;
}

Число перед функцією виклику повертає тип номера незалежно від типу фактичного значення, що повертається, як показано у другому виклику, де typeof rc = число, але значення NaN

the console.log для вищезазначеного:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.