为函数参数设置类型?

是否有一种方法可以让javascript函数知道某个参数是某个类型的?

能够做这样的事情将是完美的:

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

谢谢你!

更新:如果答案是一个响亮的“不”,如果我想myDate被视为一个日期(为了在它上面调用日期函数),我必须在函数内部将它转换为日期或设置一个date类型的新变量?

296232 次浏览

不,JavaScript不是静态类型语言。有时可能需要手动检查函数体中的参数类型。

不,相反,你需要根据你的需要做这样的事情:

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

不是在javascript中,而是使用谷歌闭包编译器的高级模式,你可以这样做:

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

这可以很容易地用ArgueJS来完成:

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

编辑:七年后,这个答案仍然偶尔会得到点赞。如果您正在寻找运行时检查,这很好,但我现在建议使用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

看看来自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

这里是如何运行它

虽然你不能通知JavaScript 的语言类型,但你可以通知IDE类型,这样你就可以得到更有用的自动补全。

这里有两种方法:

  1. 使用JSDoc,一个用于在注释中记录JavaScript代码的系统。特别地,你需要@param指令:

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

    你也可以使用JSDoc来定义自定义类型并在@param指令中指定它们,但注意JSDoc不会做任何类型检查;它只是一个文档工具。要检查JSDoc中定义的类型,请查看打印稿,它可以解析JSDoc标签.

    . 0
  2. 使用类型提示,在a
    的参数前指定类型 /* comment */: < / p >

    JavaScript类型提示在WebStorm

    这是一个相当广泛的技术,例如使用由ReactJS。对于传递给第三方库的回调参数非常方便

打印稿

对于实际的类型检查,最接近的解决方案是使用TypeScript, JavaScript的(主要是)超集。这是TypeScript只需5分钟

使用typeofinstanceof:

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');
}

你可以在函数中使用包装器实现一个自动处理类型检查的系统。

使用这种方法,你可以构建一个完整的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

也许是这样的辅助函数。但如果你发现自己经常使用这样的语法,你可能应该切换到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
}

我也一直在考虑这个问题。从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返回一个Number类型,而不管实际返回值的类型是什么,就像在第二次调用中看到的,其中typeof rc = Number但值是NaN

上面的console.log是:

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

TypeScript是目前最好的解决方案之一。

TypeScript通过向语言中添加类型来扩展JavaScript。

Typescript版本演示

// type alias
type myDateType = Date;
type myStringType = string;


function myFunction(myDate: myDateType, myString: myStringType) {
// do stuff
console.log(`myDate =`, myDate);
console.log(`myString =`, myString);
}


myFunction(new Date(), 'TypeScript is awesome!');


试着在线玩这个游乐场

参考文献

https://www.typescriptlang.org/

解释

我不确定我的答案是否直接回答了最初的问题,但我想很多人来这里只是为了找到告诉他们的ide理解类型的方法,我将分享我的发现。

如果你想告诉VSCode来理解你的类型,按照下面的步骤做。请注意,js运行时和NodeJS根本不关心这些类型。

解决方案

1-创建一个以.d.ts结尾的文件:例如:index.d.ts。您可以在另一个文件夹中创建此文件。例如:types/index.d.ts
2-假设我们想要有一个名为view的函数。将这些行添加到index.d.ts:

/**
* Use express res.render function to render view file inside layout file.
*
* @param {string} view The path of the view file, relative to view root dir.
* @param {object} options The options to send to view file for ejs to use when rendering.
* @returns {Express.Response.render} .
*/
view(view: string, options?: object): Express.Response.render;

3-在你项目的根目录中创建一个jsconfig.json文件。(看起来仅仅创建这个文件就足以让VSCode搜索你的类型了)。

再多一点

现在假设我们想把这个类型添加到另一个库类型中。(就我自己的情况而言)。我们可以使用一些ts关键字。只要VSCode理解ts,我们就没有问题。< br > 例如,如果你想将这个view函数添加到response from expressjs中,修改index.d.ts文件如下
export declare global {
namespace Express {
interface Response {
/**
* Use express res.render function to render view file inside layout file.
*
* @param {string} view The path of the view file, relative to view root dir.
* @param {object} options The options to send to view file for ejs to use when rendering.
* @returns {Express.Response.render} .
*/
view(view: string, options?: object): Express.Response.render;
}
}
}

结果

enter image description here

enter image description here

我假设您允许IDE帮助您;那么下面的答案可能会帮助你。

Ide: __abc0 __abc1

并且它可以很好地显示JSDoc

演示

/pkg/encoding/base64.js

/**
* Convert string to the base64 format.
*
* @param str {string} Input string
* @returns {string} some message about return...
* @example
*  - btoa(toBinary("☸☹☺☻☼☾☿"))
*  - Str2base64("☸☹☺☻☼☾☿")
* @see https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa#unicode_strings
*/
export function Str2base64(str) {
return btoa(toBinary(str))
}

. js

import * as base64 from "../pkg/encoding/base64"
const filenameB64 = base64.Str2base64("test")

enter image description here

有用的JSDoc文档

  • < a href = " https://jsdoc。app/# Block - Tags " rel="nofollow noreferrer">JSDoc块标签
    • 显示@returns@param@type

其他链接