Pregunta

How can I test if a variable is an array of string in TypeScript? Something like this:

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

Edit: I've updated the text to ask for a test for string[]. This was only in the code example previously.

¿Fue útil?

Solución

You cannot test for string[] in the general case but you can test for Array quite easily the same as in JavaScript https://stackoverflow.com/a/767492/390330 (I prefer Array.isArray(value)).

If you specifically want for string array you can do something like:

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

In case you need to check for an array of a class (not a basic type)

if(items && (items.length > 0) && (items[0] instanceof MyClassName))

If you are not sure that all items are same type

items.every(it => it instanceof MyClassName)

Otros consejos

Another option is Array.isArray()

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

Here is the most concise solution so far:

function isArrayOfStrings(value: unknown): value is string[] {
   return Array.isArray(value) && value.every(item => typeof item === "string");
}

Note that value.every returns true for an empty array. To return false for an empty array, add value.length > 0 to the condition clause:

function isNonEmptyArrayOfStrings(value: unknown): value is string[] {
    return Array.isArray(value) && value.length > 0 && value.every(item => typeof item === "string");
}

There is no any run-time type information in TypeScript (and there won't be, see TypeScript Design Goals > Non goals, 5), so there is no way to get the "type" of elements of an empty array. For non-empty array all you can do is to check the type of its items, one by one.

Type predicate value is string[] narrows type of value to string[] in the corresponding scope. This is a TypeScript feature, the real return type of the function is boolean.

I know this has been answered, but TypeScript introduced type guards: https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards

If you have a type like: Object[] | string[] and what to do something conditionally based on what type it is - you can use this type guarding:

function isStringArray(value: any): value is string[] {
  if (value instanceof Array) {
    for (const item of 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
  }
}

There is an issue with an empty array being typed as string[], but that might be okay

Try this:

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

You can have do it easily using Array.prototype.some() as below.

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

I believe this approach is better that others. That is why I am posting this answer.

Update on Sebastian Vittersø's comment

Here you can use Array.prototype.every() as well.

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

Referring to the type-guards (https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards), you can do something like ->

/**
 * type-guard function to check at run-time if all the elements inside
 * from the array are strings
 * @param array
 * @returns - boolean, true if the array is string array
 */
export function isStringArray(array: unknown[]): array is string[] {
  return array.every((element) => typeof element === 'string')
}

there is a little problem here because the

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

will not stop the foreach. So the function will return true even if the array does contain none string values.

This seems to wok for me:

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

Greetings, Hans

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top