Przetestuj tablicę typu ciągów w języku TypeScript


99

Jak mogę sprawdzić, czy zmienna jest tablicą ciągów w języku TypeScript? Coś takiego:

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 tutaj: http://typescript.io/k0ZiJzso0Qg/2

Edycja: zaktualizowałem tekst, aby poprosić o test dla ciągu []. Było to tylko w poprzednim przykładzie kodu.



Ponieważ TypeScript kompiluje się tylko do JavaScript, odpowiedzi można znaleźć, wyszukując rozwiązanie JavaScript. Co więcej, warto zapoznać się z niektórymi odpowiedziami, ponieważ odpowiedź zależy od hosta oraz tego, jak jest używany i przekazywany.
— WiredPrairie

Odpowiedzi:


173

W string[]ogólnym przypadku nie możesz przetestować, ale możesz łatwo przetestować Arrayto samo, co w JavaScript https://stackoverflow.com/a/767492/390330

Jeśli chcesz specjalnie dla stringtablicy, możesz zrobić coś takiego:

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 Arraykończy się niepowodzeniem podczas sprawdzania tablic w ramkach. Wolisz Array.isArray: twitter.com/mgechev/status/1292709820873748480
— axmrnv

@axmrnv Całkowicie się zgadzam 🌹
— basarat

możesz również przerwać pętlę zaraz po powiedzeniu, że coś jestIsNotString. Wraz z Twoim kodem koniecznie przejdzie przez całą tablicę, co nie jest konieczne.
— Kukuster

58

Inną opcją jest Array.isArray ()

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

4
Ale to nie sprawdza, czy elementy są typu string.
— Ixx

4
Yeap. Następnie potrzebujesz jeszcze jednego sprawdzenia. Array.isArray(classNames) && classNames.every(it => typeof it === 'string')
— grigson

@grigson a co z wydajnością podczas sprawdzania ponad 400 wyników? Powinienem zignorować tego rodzaju kontrolę typu, sprawdzić tylko pierwsze dziecko, czy bezpiecznie jest używać tego „wszystkiego”?
— giovannipds

1
@giovannipds Sprawdź odpowiedź asmironova .
— Dinei

25

Oto jak dotąd najbardziej zwięzłe rozwiązanie:

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

Zauważ, że value.everyzwróci trueto pustą tablicę. Jeśli chcesz zwrócić falsepustą tablicę, powinieneś dodać value.lengthdo klauzuli warunku:

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

W TypeScript nie ma żadnych informacji o typie wykonawczym (i nie będzie, zobacz Cele projektowe TypeScript> Inne niż cele , 5), więc nie ma sposobu, aby uzyskać typ pustej tablicy. W przypadku niepustej tablicy jedyne, co możesz zrobić, to sprawdzić typ jej elementów, jeden po drugim.


6

Wiem, że na to odpowiedziano, ale TypeScript wprowadził zabezpieczenia typów: https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards

Jeśli masz typ typu: Object[] | string[]i co zrobić warunkowo na podstawie tego, jaki to typ - możesz użyć tego typu ochrony:

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

Występuje problem z wpisywaniem pustej tablicy jako string[], ale może to być w porządku


10
return falseW forEachnie ma żadnego wpływu.
— Isztar

4

Możesz to zrobić z łatwością, Array.prototype.some()jak poniżej.

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

Uważam, że takie podejście jest lepsze niż inne. Dlatego zamieszczam tę odpowiedź.

Najnowsze informacje na temat komentarza Sebastiana Vittersø

Tutaj możesz również użyć Array.prototype.every().

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

1
Zamiast używać negacji w dwóch miejscach tutaj, możesz zrobić:test.every(value => typeof value === 'string')
— Sebastian

1
@ SebastianVittersø Dzięki za NICE sugestię. Zaktualizowałem odpowiedź.
— Sudarshana Dayananda

2

Spróbuj tego:

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

6
Zamiast kopiować inną odpowiedź, po prostu wskaż duplikat jako komentarz, zwłaszcza, że ​​nie działa to we wszystkich przypadkach.
— WiredPrairie

To po prostu sprawdź główny typ nie każdego dziecka Array.
— giovannipds

0

jest tu mały problem, ponieważ

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

nie zatrzyma foreach. Zatem funkcja zwróci wartość true, nawet jeśli tablica nie zawiera żadnych wartości łańcuchowych.

To wydaje się działać dla mnie:

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

Pozdrowienia, Hans

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.