TypeScript'te dizi türü için test edin


95

Bir değişkenin TypeScript'te bir dizi dizisi olup olmadığını nasıl test edebilirim? Bunun gibi bir şey:

function f(): string {
    var a: string[] = ["A", "B", "C"];

    if (typeof a === "string[]")    {
        return "Yes"
    }
    else {
        // returns no as it's 'object'
        return "No"
    }
};

TypeScript.io burada: http://typescript.io/k0ZiJzso0Qg/2

Düzenleme: Metni [] dizesi için bir test isteyecek şekilde güncelledim. Bu sadece daha önce kod örneğindeydi.



TypeScript yalnızca JavaScript'i derlediğinden, yanıtlar bir JavaScript çözümü arayarak bulunabilir. Ayrıca, cevap ev sahibine ve nasıl kullanıldığı ve geçildiğine bağlı olduğundan bazı cevapları görmeye değer.
WiredPrairie

Yanıtlar:


164

Sen test edemez string[]genel durumda ancak test edebilirsiniz ArrayJavaScript gibi oldukça kolay aynı https://stackoverflow.com/a/767492/390330

stringDiziyi özellikle istiyorsanız, aşağıdaki gibi bir şey yapabilirsiniz:

if (Array.isArray(value)) {
   var somethingIsNotString = false;
   value.forEach(function(item){
      if(typeof item !== 'string'){
         somethingIsNotString = true;
      }
   })
   if(!somethingIsNotString && value.length > 0){
      console.log('string[]!');
   }
}

instanceof Arraykareler arasında dizileri kontrol ederken başarısız olur. Tercih Array.isArray: twitter.com/mgechev/status/1292709820873748480
axmrnv

@axmrnv Tamamen katılıyorum 🌹
basarat

Ayrıca, somethingIsNotString olduğunu söyledikten hemen sonra döngüyü kırabilirsiniz. Kodunuzla, gerekli olmayan tüm dizide mutlaka döngü olacaktır.
Kukuster

58

Diğer bir seçenek ise Array.isArray ()

if(! Array.isArray(classNames) ){
    classNames = [classNames]
}

4
Ancak bu, türdeki unsurları kontrol etmez string.
Ixx

4
Evet. O zaman ek bir kontrole ihtiyacınız var. Array.isArray(classNames) && classNames.every(it => typeof it === 'string')
grigson

@grigson 400'den fazla sonucu kontrol ederken performansa ne dersiniz? Bu tür kontrolleri göz ardı etmeli miyim, sadece ilk çocuğu kontrol etmeli miyim yoksa bu "her" şeyi kullanmak güvenli mi?
giovannipds

1
@giovannipds Lütfen asmironov'un cevabını kontrol edin .
Dinei

24

Şimdiye kadarki en kısa çözüm şudur:

function isArrayOfStrings(value: any): boolean {
   return Array.isArray(value) && value.every(item => typeof item === "string");
}

Boş bir dizi için value.everydöneceğini unutmayın true. falseBoş bir dizi için geri dönmeniz gerekiyorsa value.length, koşul cümlesine eklemelisiniz :

function isNonEmptyArrayOfStrings(value: any): boolean {
    return Array.isArray(value) && value.length && value.every(item => typeof item === "string");
}

TypeScript'te herhangi bir çalışma zamanı türü bilgisi yoktur (ve olmayacaktır, bkz. TypeScript Tasarım Hedefleri> Hedef olmayanlar , 5), bu nedenle boş bir dizinin türünü almanın bir yolu yoktur. Boş olmayan bir dizi için yapabileceğiniz tek şey, öğelerinin türünü tek tek kontrol etmektir.


5

Bunun yanıtlandığını biliyorum, ancak TypeScript tür koruyucuları tanıttı: https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards

Gibi bir türünüz varsa Object[] | string[]ve ne tür olduğuna bağlı olarak koşullu olarak ne yapmanız gerektiği - bu tür korumayı kullanabilirsiniz:

function isStringArray(value: any): value is string[] {
  if (value instanceof Array) {
    value.forEach(function(item) { // maybe only check first value?
      if (typeof item !== 'string') {
        return false
      }
    })
    return true
  }
  return false
}

function join<T>(value: string[] | T[]) {
  if (isStringArray(value)) {
    return value.join(',') // value is string[] here
  } else {
    return value.map((x) => x.toString()).join(',') // value is T[] here
  }
}

Olarak yazılan boş bir diziyle ilgili bir sorun var string[], ancak bu sorun olmayabilir


10
return falseİçinde forEachhiçbir etkisi olmaz.
Ishtar

4

Array.prototype.some()Aşağıdaki gibi kullanarak kolaylıkla yaptırabilirsiniz .

const isStringArray = (test: any[]): boolean => {
 return Array.isArray(test) && !test.some((value) => typeof value !== 'string')
}
const myArray = ["A", "B", "C"]
console.log(isStringArray(myArray)) // will be log true if string array

Bu yaklaşımın diğerlerinden daha iyi olduğuna inanıyorum. Bu yüzden bu cevabı gönderiyorum.

Sebastian Vittersø'nun yorumuyla ilgili güncelleme

Burada da kullanabilirsiniz Array.prototype.every().

const isStringArray = (test: any[]): boolean => {
 return Array.isArray(test) && test.every((value) => typeof value === 'string')
}

1
Burada iki yerde olumsuzluk kullanmak yerine şunları yapabilirsiniz:test.every(value => typeof value === 'string')
Sebastian

1
@ SebastianVittersø GÜZEL öneriniz için teşekkürler. Cevabımı güncelledim.
Sudarshana Dayananda

2

Bunu dene:

if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}

6
Başka bir cevabı kopyalamak yerine, lütfen kopyayı bir yorum olarak işaret edin, özellikle bu her durumda işe yaramayacağı için.
WiredPrairie

Bu sadece her Dizinin alt öğesini değil ana türü kontrol eder.
giovannipds

0

burada küçük bir sorun var çünkü

if (typeof item !== 'string') {
    return false
}

foreach'ı durdurmayacak. Dolayısıyla, dizi hiçbir dize değeri içermese bile işlev true değerini döndürür.

Bu benim için uyanmış gibi görünüyor:

function isStringArray(value: any): value is number[] {
  if (Object.prototype.toString.call(value) === '[object Array]') {
     if (value.length < 1) {
       return false;
     } else {
       return value.every((d: any) => typeof d === 'string');
     }
  }
  return false;
}

Selamlar, Hans

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.