Test for array of string type in TypeScript
TypescriptTypescript Problem Overview
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.
Typescript Solutions
Solution 1 - Typescript
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)
Solution 2 - Typescript
Another option is Array.isArray()
if(! Array.isArray(classNames) ){
classNames = [classNames]
}
Solution 3 - Typescript
Here is the most concise solution so far:
function isArrayOfStrings(value: any): boolean {
return Array.isArray(value) && value.every(item => typeof item === "string");
}
Note that value.every
will return true
for an empty array. If you need to return false
for an empty array, you should add value.length
to the condition clause:
function isNonEmptyArrayOfStrings(value: any): boolean {
return Array.isArray(value) && value.length && 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 an empty array. For a non-empty array all you can do is to check the type of its items, one by one.
Solution 4 - Typescript
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
Solution 5 - Typescript
Try this:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
Solution 6 - Typescript
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')
}
Solution 7 - Typescript
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