İşlev parametreleri için tür ayarlansın mı?


162

Bir javascript işlevinin belirli bir parametrenin belirli türde olduğunu bilmesini sağlamanın bir yolu var mı?

Böyle bir şey yapabilmek mükemmel olurdu:

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

Teşekkür ederim!

Güncelleme : Cevabın "hayır" gibi yankılanması myDateolarak, tarih olarak değerlendirilmek istiyorsam (tarih işlevlerini çağırmak için), işlevin içinde bir tarih olarak yayınlamam veya yeni bir değişken ayarlamam gerekir. Tarih yazılsın mı?


1
Yerleşik ve genel anlamda değil. Bunu kendiniz yapabilirsiniz, ancak daha sonra "belirli bir tür"
ü

2
JavaScript'te de sınıf yok, bu yüzden Datesadece yok object.
kurtulmak


@dmr, bu bir sınıf değil. Datebir işlevdir. JavaScript anahtar kelimesi hakkında daha fazla bilgi edinmek için stackoverflow.com/questions/1646698/… adresine bakın new. Ayrıca, sınıf olmadığı için döküm yoktur. İstediğiniz işlevleri çağırabilirsiniz. Nesne bunları içeriyorsa, çalışırlar, aksi takdirde bir hata alırsınız.
kurtulun

2
Ancak bu eski bir
kit

Yanıtlar:


181

Hayır, JavaScript statik olarak yazılmış bir dil değildir. Bazen işlev gövdesindeki parametre türlerini el ile kontrol etmeniz gerekebilir.


180
Bereket ve bir lanet.
Jeffrey Sweeney

40
@JeffreySweeney PHP'nin statik olarak yazılmadığı anlamına gelir. Ama php tür ipucu yapmak için seçeneğiniz var. Hiç büyük bir nodejs arka uç uygulamasına baktınız mı? tam olarak, her fonksiyonun argümanları vardır ve her argümanın ne olduğuna dair hiçbir ipucunuz yoktur. Binlerce argümandan bahsediyoruz ve okurken, tüm kodu ve arayanın ve arayanın tüm kodunu vb. Okumalısınız. Blessing? kesinlikle şaka yapıyor olmalısın.
Toskan

14
Bir tür nimet izin veren hiçbir özelliği çağıran biri bashing dışında ben şunu vurgulamak isteyebilirsiniz typescript: typescriptlang.org temelde EM6 + tip ima
Toskan

23
@JeffreySweeney Bu bir nimet değil. Kanser.
Robo Robok

1
@Toskan Bunun bir nimet olmadığını söyleyemem. Dört yıldır JavaScript kullanıyorum ve bu sadece bazı dillerin doğası. Programlama dilleri kümesi olmalıdır zayıf kuvvetle yüksek seviyeye düşük seviyeden aralığında olmalıdır aynı şekilde daktilo yazdığınız arasında değişir. Ayrıca, JavaScript buna yardımcı olacak instanceofve typeofanahtar sözcükleri sağlar . Bu daha fazla kod gerektirse de, büyük ölçüde türlere bağlı olan bir şeyin dili olarak JavaScript'i seçmek geliştiricide olabilir. Büyük nodejs arka uç uygulamaları gelince? Bence sağduyu olmalı.
Marvin

83

Kendi kendine javascript değil, Google Closure Compiler'ın gelişmiş modunu kullanarak bunu yapabilirsiniz:

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

Bkz. Http://code.google.com/closure/compiler/docs/js-for-compiler.html


1
bu aynı zamanda Eclipse JavaScript Editor - Anahat Görünümü ve Kod Tamamlama ile çalışır / etkinleştirir . oysa foo( /*MyType*/ param )burada açıklanan yol da işe
Andreas Dietrich

Bu sorunun kaç yaşında olduğunun farkındayım, ancak IntelliJ'de onurlandırıldığını belirtmek istedim. Burada çok küçük bir cevap.
ChettDM

67

JavaScript'i dil hakkında türler hakkında bilgilendiremeseniz de, IDE'nizi bunlar hakkında bilgilendirebilirsiniz, böylece çok daha kullanışlı otomatik tamamlama elde edersiniz.

İşte bunu yapmanın iki yolu:

  1. Yorumlardaki JavaScript kodunu belgelemek için kullanılan bir sistem olan JSDoc'u kullanın . Özellikle, @paramyönerge gerekir :

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

    Özel türleri tanımlamak ve bunları @paramyönergelerde belirtmek için JSDoc'u da kullanabilirsiniz , ancak JSDoc'un herhangi bir tür denetimi yapmayacağını unutmayın; sadece bir dokümantasyon aracı. İçine JSDoc, görünüm tanımlanan türde kontrol etmek typescript hangi, JSDoc etiketlerini ayrıştırmak .

  2. A parametresinden hemen önce türü belirterek tür ipucunu kullanın
    /* comment */:

    WebStorm'da JavaScript türü ipucu

    Bu, ReactJS tarafından kullanılan oldukça yaygın bir tekniktir . 3. taraf kütüphanelere aktarılan geri arama parametreleri için çok kullanışlıdır.

daktilo ile yazılmış yazı

Gerçek tür denetimi için en yakın çözüm, JavaScript'in ( çoğunlukla ) üst kümesi olan TypeScript kullanmaktır . İşte 5 dakika içinde TypeScript .


8
Bunu nasıl alabilirim VSCode?
Anand Undavia

2
Teşekkürler. Bu IDE'ye bağlı olmasına rağmen. VI kullanıyorum ve çalışmayacağım.
negrotico19

@ negrotico19: viIDE değil, aşırı istismar edilmiş bir editördür. Sen de bir sürü şey yapabilir viyapabilirsiniz, tıpkı Excel'de müzik videoları . İyi bir fikir? Muhtemelen değil. İş için doğru aracı kullanın.
Dan Dascalescu

23

"JavaScript programlarında tür hataları bulmak için tasarlanmış statik bir tür denetleyicisi" adlı Facebook'tan yeni Flow kütüphanesine göz atın

Tanım:

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

Tip kontrolü:

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

Ve işte nasıl çalıştırılacağı .


x bir tarih türüyse tür tanımı nasıl eklenir? yani foo (x: Tarih): dize {}. Bunu yapmanın doğru yolu bu mu?
Aakash Sigdel

12

Hayır, bunun yerine ihtiyaçlarınıza bağlı olarak böyle bir şey yapmanız gerekir:

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

12

İşlevinizdeki bir sarıcı kullanarak tür denetimlerini otomatik olarak işleyen bir sistem uygulayabilirsiniz .

Bu yaklaşımla, declarative type check systemtür denetimlerini sizin için yönetecek bir tam oluşturabilirsiniz. Bu konsepte daha derinlemesine bakmak istiyorsanız , Functyped kütüphanesine bakın

Aşağıdaki uygulama, ana fikri basit ama işlevsel bir şekilde göstermektedir :

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

Edit: Yedi yıl sonra, bu cevap hala ara sıra upvotes alır. Çalışma zamanı denetimi arıyorsanız sorun değil, ancak şimdi Typcript veya muhtemelen Flow kullanarak derleme zamanı türü denetimi öneriyoruz. Daha fazla bilgi için yukarıdaki https://stackoverflow.com/a/31420719/610585 adresine bakın .

Orijinal cevap:

Dilde yerleşik değildir, ancak bunu kendiniz kolayca yapabilirsiniz. Vibhu'nun cevabı, Javascript'te tip kontrolünün tipik yolunu düşünürüm. Daha genel bir şey istiyorsanız, şöyle bir şey deneyin: (başlamanız için sadece bir örnek)

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 ile kolayca yapılabilir :

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

2
harika bir kütüphane gibi görünüyor. tebrikler.
FRD

1

typeofVeya kullanın 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

Belki böyle bir yardımcı fonksiyon. Ancak, bu tür bir sözdizimini düzenli olarak kullandığınızı görürseniz, muhtemelen Typcript'e geçmelisiniz.

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

Ben de bunu düşünüyorum. Bir C arka planından, aşağıdaki gibi bir şey kullanarak işlev dönüş kodu türlerini ve parametre türlerini simüle edebilirsiniz:

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

Arama işlevinden önceki Sayı, type = rc = number ancak değerin NaN olduğu 2. çağrıda görüldüğü gibi, döndürülen gerçek değerin türünden bağımsız olarak bir Number türü döndürür.

yukarıdaki console.log dosyası:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.