Установить тип для параметров функции?

162

Есть ли способ сообщить функции javascript, что определенный параметр имеет определенный тип?

Быть способным сделать что-то подобное было бы идеально:

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

Спасибо!

Обновление : поскольку ответом является громкое «нет», если я хочу, myDateчтобы его считали датой (чтобы вызывать для него функции даты), я должен преобразовать его как дату внутри функции или установить новую переменную Тип даты к нему?

DMR
источник
1
Не в встроенном, а в общем смысле. Вы можете сделать это самостоятельно, вручную, но тогда это зависит от того, как вы определяете «определенного типа»
hugomg
2
Там также нет классов в JavaScript, так что нет Date, только object.
избавиться
@ DMR, это не класс. Dateэто функция. Посмотрите на stackoverflow.com/questions/1646698/… чтобы узнать больше о newключевом слове JavaScript . Кроме того, поскольку нет классов, нет кастинга. Вы можете просто вызвать функции, которые вы хотите. Если объект содержит их, они будут работать, в противном случае вы получите ошибку.
избавиться
2
Это старый, но никто не упомянул машинопись
комплект

Ответы:

181

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

pronvit
источник
180
Благословение и проклятие.
Джеффри Суини
40
@JeffreySweeney также не является статически типизированным PHP. Но у вас есть возможность делать подсказки типа в php. Вы когда-нибудь смотрели на большое внутреннее приложение nodejs? точно, у каждой функции есть аргументы, и вы не знаете, что это за аргумент. Мы говорим о тысячах аргументов, и при чтении вы должны прочитать весь код, а также весь код вызывающего и вызывающего абонента и т. Д. Благословение? ты наверняка шутишь.
Тоскан
14
Помимо избиения кого-то, кто не вызывает функцию, позволяющую типу хинтовать благословение, я мог бы указать на машинописный текст: typescriptlang.org в основном EM6 + хинтинг типов
Toskan
23
@JeffreySweeney Это не благословение. Это рак.
Робо Робок
1
@Toskan Я бы не сказал, что это не благословение. Я использую JavaScript уже четыре года, и это просто природа некоторых языков. Набор языков программирования должен варьироваться от слабо типизированных до строго типизированных так же, как он должен варьироваться от низкого уровня до высокого уровня. Кроме того, JavaScript предоставляет instanceofи typeofключевые слова , чтобы помочь в этом. Хотя для этого требуется больше кода, возможно, именно разработчик выбрал JavaScript в качестве языка для чего-то, что в значительной степени зависит от типов. Что касается огромных серверных приложений nodejs? Я думаю, что это должно быть здравым смыслом.
Марвин
82

Не в javascript, а в расширенном режиме компилятора Google вы можете сделать это:

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

eolsson
источник
1
это также работает с / включает Eclipse JavaScript Editor - Outline View и Завершение кода . тогда foo( /*MyType*/ param )как описанный здесь способ также работает: stackoverflow.com/a/31420719/1915920
Андреас Дитрих
Я понимаю, сколько лет этому вопросу, но я хотел бы отметить, что он удостоен чести в IntelliJ. Очень недооцененный ответ здесь.
ChettDM
67

Хотя вы не можете сообщить языку JavaScript о типах, вы можете сообщить в 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, (в основном ) расширенного набора JavaScript. Вот TypeScript через 5 минут .

Дан Дакалеску
источник
8
Как это сделать VSCode?
Ананд Ундавиа,
2
Спасибо. Хотя это зависит от IDE. Я использую VI и не буду работать.
negrotico19
@ negrotico19: viредактор, которым злоупотребляют, а не IDE. Вы можете делать много чего vi, так же, как вы можете делать музыкальные клипы в Excel . Отличная идея? Возможно нет. Используйте правильный инструмент для работы.
Дан Даскалеску
23

Ознакомьтесь с новой библиотекой Flow от 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

И вот как это запустить .

Renaud
источник
Как добавить определение типа, если х был тип даты? то есть foo (x: Date): строка {}. это правильный способ сделать это?
Аакаш Сигдел
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

colxi
источник
11

Изменить: семь лет спустя, этот ответ все еще получает случайные отзывы. Хорошо, если вы ищете проверку во время выполнения, но я бы сейчас порекомендовал проверку типов во время компиляции с использованием Typescript или, возможно, Flow. См. Https://stackoverflow.com/a/31420719/610585 выше для получения дополнительной информации.

Оригинальный ответ:

Это не встроено в язык, но вы можете сделать это самостоятельно довольно легко. Ответ Вибху - это то, что я считаю типичным способом проверки типов в 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
};
zVictor
источник
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');
}
Fider
источник
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
}
phil294
источник
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;
}

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

console.log для вышеупомянутого:

1st call
typeof rc: number   rc: 1
2nd call
Parm 1 not correct type
typeof rc: number   rc: NaN
деревенщина
источник