Setel jenis untuk parameter fungsi?

161

Apakah ada cara untuk membiarkan fungsi javascript tahu bahwa parameter tertentu adalah tipe tertentu?

Mampu melakukan sesuatu seperti ini akan menjadi sempurna:

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

Terima kasih!

Pembaruan : Karena jawabannya adalah "tidak," jika saya ingin myDatediperlakukan sebagai tanggal (untuk memanggil fungsi tanggal di dalamnya), saya harus memasukkannya sebagai tanggal di dalam fungsi atau menetapkan variabel baru dari ketik Date to it?

dmr
sumber
1
Tidak dalam pengertian umum dan umum. Anda bisa melakukannya sendiri, dengan tangan, tetapi tergantung bagaimana Anda mendefinisikan "tipe tertentu"
hugomg
2
Juga tidak ada kelas dalam JavaScript, jadi tidak ada Date, hanya object.
singkirkan
@ Radu: Bagaimana dengan Halaman Jaringan Mozilla Develop ini ?
dmr
@ dmr, itu bukan kelas. Dateadalah suatu fungsi. Lihatlah stackoverflow.com/questions/1646698/… untuk mengetahui lebih lanjut tentang newkata kunci JavaScript . Juga, karena tidak ada kelas, tidak ada casting. Anda cukup memanggil fungsi yang Anda inginkan. Jika objek berisi mereka, mereka akan berjalan, jika tidak Anda akan mendapatkan kesalahan.
singkirkan
2
Ini yang lama namun tidak ada yang menyebutkan naskah
kit

Jawaban:

180

Tidak, JavaScript bukan bahasa yang diketik secara statis. Terkadang Anda mungkin perlu memeriksa jenis parameter secara manual di badan fungsi Anda.

pronvit
sumber
180
Berkah dan kutukan.
Jeffrey Sweeney
40
@JeffreySweeney tidak memiliki PHP yang diketik secara statis. Tetapi Anda memiliki opsi untuk melakukan mengetikkan petunjuk di php. Pernahkah Anda melihat aplikasi backend nodejs besar ? tepatnya, setiap fungsi memiliki argumen, dan Anda tidak memiliki petunjuk apa pun setiap argumen. Kita berbicara tentang ribuan argumen dan ketika membaca, Anda harus membaca seluruh kode, dan seluruh kode penelepon dan peneleponnya, dll. Berkat? Anda tentu harus bercanda.
Toskan
14
selain dari memukul seseorang yang menyebut tidak ada fitur yang memungkinkan tipe mengisyaratkan berkah, saya mungkin ingin menunjukkan naskah: typescriptlang.org dasarnya EM6 + tipe hinting
Toskan
23
@ JeffreySweeney Ini bukan berkah. Itu kanker.
Robo Robok
1
@Toskan Saya tidak akan mengatakan itu bukan berkah. Saya telah menggunakan JavaScript selama empat tahun sekarang, dan itu hanya sifat beberapa bahasa. Rangkaian bahasa pemrograman harus berkisar dari yang diketik dengan lemah hingga sangat diketik dengan cara yang sama mulai dari level rendah ke level tinggi. Selain itu, JavaScript menyediakan instanceofdan typeofkata kunci untuk membantu dalam hal ini. Meskipun ini membutuhkan lebih banyak kode, mungkin itu pada pengembang untuk memilih JavaScript sebagai bahasa untuk sesuatu yang sangat tergantung pada jenis. Adapun aplikasi backend nodejs besar? Saya pikir itu harus masuk akal.
Marvin
82

Tidak dalam javascript sendiri tetapi menggunakan mode lanjutan Google Closure Compiler Anda dapat melakukannya:

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

Lihat http://code.google.com/closure/compiler/docs/js-for-compiler.html

eolsson
sumber
1
ini juga berfungsi dengan / mengaktifkan Eclipse JavaScript Editor - Tampilan Garis Besar dan Penyelesaian Kode . sedangkan foo( /*MyType*/ param )cara seperti yang dijelaskan di sini juga berfungsi: stackoverflow.com/a/31420719/1915920
Andreas Dietrich
Saya menyadari berapa umur pertanyaan ini, tetapi saya ingin menunjukkan bahwa itu dihargai di IntelliJ. Jawaban yang sangat diremehkan di sini.
ChettDM
67

Meskipun Anda tidak dapat memberi tahu JavaScript tentang jenis bahasa , Anda dapat memberi tahu IDE tentang JavaScript , sehingga Anda mendapatkan pelengkapan otomatis yang jauh lebih bermanfaat.

Berikut adalah dua cara untuk melakukan itu:

  1. Gunakan JSDoc , sistem untuk mendokumentasikan kode JavaScript dalam komentar. Secara khusus, Anda perlu @paramarahan :

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

    Anda juga dapat menggunakan JSDoc untuk mendefinisikan tipe kustom dan menentukan yang ada dalam @paramarahan, tetapi perhatikan bahwa JSDoc tidak akan melakukan pengecekan tipe apa pun; itu hanya alat dokumentasi. Untuk memeriksa jenis yang didefinisikan dalam JSDoc, lihatlah ke TypeScript , yang dapat mengurai tag JSDoc .

  2. Gunakan tipe hinting dengan menentukan tipe tepat sebelum parameter di
    /* comment */:

    Petunjuk tipe JavaScript di WebStorm

    Ini adalah teknik yang cukup luas, digunakan oleh ReactJS misalnya. Sangat berguna untuk parameter callback yang diteruskan ke perpustakaan pihak ke-3.

TypeScript

Untuk pengecekan tipe aktual, solusi terdekat adalah menggunakan TypeScript, sebuah superset JavaScript ( kebanyakan ). Inilah TypeScript dalam 5 menit .

Dan Dascalescu
sumber
8
Bagaimana cara mengaktifkannya VSCode?
Anand Undavia
2
Terima kasih. Meskipun ini tergantung pada IDE. Saya menggunakan VI dan tidak akan berfungsi.
negrotico19
@ negrotico19: viadalah editor yang terlalu banyak disalahgunakan, bukan IDE. Anda dapat melakukan banyak hal vi, sama seperti Anda dapat membuat video musik di Excel . Ide bagus? Mungkin tidak. Gunakan alat yang tepat untuk pekerjaan itu.
Dan Dascalescu
23

Lihat Aliran baru pustaka dari Facebook, "pemeriksa tipe statis, yang dirancang untuk menemukan kesalahan jenis dalam program JavaScript"

Definisi:

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

Pengecekan tipe:

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

Dan inilah cara menjalankannya .

Renaud
sumber
bagaimana cara menambahkan definisi tipe jika x adalah tipe tanggal? yaitu foo (x: Tanggal): string {}. apakah ini cara yang tepat untuk melakukannya?
Aakash Sigdel
12

Tidak, sebagai gantinya Anda perlu melakukan sesuatu seperti ini tergantung pada kebutuhan Anda:

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

Anda dapat menerapkan sistem yang menangani pemeriksaan tipe secara otomatis , menggunakan pembungkus pada fungsi Anda.

Dengan pendekatan ini, Anda bisa membuat lengkap declarative type check systemyang akan mengelola untuk Anda tipe cek. Jika Anda tertarik untuk melihat lebih dalam pada konsep ini, periksa perpustakaan Functyped

Implementasi berikut menggambarkan ide utama, dengan cara yang sederhana, tetapi operatif :

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

Sunting: Tujuh tahun kemudian, jawaban ini kadang-kadang mendapat perbaikan. Tidak apa-apa jika Anda mencari pengecekan runtime, tetapi sekarang saya akan merekomendasikan pengecekan tipe kompilasi-waktu menggunakan Typefot, atau mungkin Flow. Lihat https://stackoverflow.com/a/31420719/610585 atas untuk informasi lebih lanjut.

Jawaban asli:

Itu tidak dibangun ke dalam bahasa, tetapi Anda dapat melakukannya sendiri dengan mudah. Jawaban Vibhu adalah apa yang saya anggap cara tipikal mengetik pengecekan dalam Javascript. Jika Anda ingin sesuatu yang lebih umum, coba sesuatu seperti ini: (hanya sebuah contoh untuk membantu Anda memulai)

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
tidak terdefinisi
sumber
5

Ini dapat dengan mudah dilakukan dengan ArgueJS :

function myFunction ()
{
  arguments = __({myDate: Date, myString: String});
  // do stuff
};
zVictor
sumber
2
tampak seperti perpustakaan yang bagus. selamat.
FRD
1

Gunakan typeofatau 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
sumber
0

Mungkin fungsi pembantu seperti ini. Tetapi jika Anda melihat diri Anda menggunakan sintaksis seperti itu secara teratur, Anda mungkin harus beralih ke Agenda.

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
sumber
0

Saya sudah memikirkan ini juga. Dari latar belakang C, Anda dapat mensimulasikan jenis kode pengembalian fungsi, serta, tipe parameter, menggunakan sesuatu seperti berikut:

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

Nomor sebelum fungsi panggilan mengembalikan tipe angka terlepas dari jenis nilai aktual yang dikembalikan, seperti yang terlihat pada panggilan kedua di mana typeof rc = angka tetapi nilainya NaN

log.log untuk di atas adalah:

1st call
typeof rc: number   rc: 1
2nd call
Parm 1 not correct type
typeof rc: number   rc: NaN
Orang udik
sumber
0

TypeScript adalah salah satu solusi terbaik untuk saat ini

TypeScript memperluas JavaScript dengan menambahkan jenis ke bahasa.

https://www.typescriptlang.org/

xgqfrms
sumber