Kiểm tra mảng kiểu chuỗi trong TypeScript


95

Làm cách nào để kiểm tra xem một biến có phải là một mảng chuỗi trong TypeScript không? Một cái gì đó như thế này:

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 tại đây: http://typescript.io/k0ZiJzso0Qg/2

Chỉnh sửa: Tôi đã cập nhật văn bản để yêu cầu kiểm tra chuỗi []. Điều này chỉ có trong ví dụ mã trước đây.



Vì TypeScript chỉ biên dịch sang JavaScript, câu trả lời có thể được tìm thấy bằng cách tìm kiếm giải pháp JavaScript. Hơn nữa, rất đáng để xem một số câu trả lời vì câu trả lời phụ thuộc vào máy chủ lưu trữ và cách nó được sử dụng và thông qua.
— WiredPrairie

Câu trả lời:


164

Bạn không thể kiểm tra string[]trong trường hợp chung nhưng bạn có thể kiểm tra Arraykhá dễ dàng giống như trong JavaScript https://stackoverflow.com/a/767492/390330

Nếu bạn muốn đặc biệt cho stringmảng, bạn có thể làm như sau:

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 Arraykhông thành công khi kiểm tra các mảng trên các khung. Ưu tiên Array.isArray: twitter.com/mgechev/status/1292709820873748480
— axmrnv

@axmrnv Hoàn toàn đồng ý 🌹
— basarat

ngoài ra, bạn có thể phá vỡ vòng lặp ngay sau khi nói với điều gì đóIsNotString. Với mã của bạn, nó nhất thiết sẽ lặp qua tất cả toàn bộ mảng, điều này không cần thiết.
— Kukuster

58

Một tùy chọn khác là Array.isArray ()

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

4
Nhưng điều này không kiểm tra các phần tử thuộc loại string.
— Ixx

4
Đúng vậy. Sau đó, bạn cần một lần kiểm tra bổ sung. Array.isArray(classNames) && classNames.every(it => typeof it === 'string')
— grigson

@grigson thì sao về hiệu suất khi kiểm tra hơn 400 kết quả? Tôi có nên từ chối loại kiểm tra kiểu này, chỉ kiểm tra đứa trẻ đầu tiên hay nó an toàn khi sử dụng "mọi thứ" này?
— giovannipds

1
@giovannipds Vui lòng kiểm tra câu trả lời của asmironov .
— Dinei

24

Đây là giải pháp ngắn gọn nhất cho đến nay:

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

Lưu ý rằng value.everysẽ trả về truemột mảng trống. Nếu bạn cần trả về falsemột mảng trống, bạn nên thêm value.lengthvào mệnh đề điều kiện:

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

Không có bất kỳ thông tin nào về kiểu thời gian chạy trong TypeScript (và sẽ không có, hãy xem Mục tiêu thiết kế TypeScript> Không phải mục tiêu , 5), vì vậy không có cách nào để lấy kiểu của một mảng trống. Đối với một mảng không trống, tất cả những gì bạn có thể làm là kiểm tra loại mục của nó, từng cái một.


5

Tôi biết điều này đã được trả lời, nhưng TypeScript đã giới thiệu bộ bảo vệ kiểu: https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards

Nếu bạn có một kiểu như: Object[] | string[]và phải làm gì có điều kiện dựa trên kiểu đó là gì - bạn có thể sử dụng kiểu bảo vệ này:

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

Đã xảy ra sự cố với mảng trống được nhập là string[], nhưng điều đó có thể ổn


10
Các return falsetrong forEachkhông có tác dụng.
— Ishtar

4

Bạn có thể thực hiện dễ dàng bằng cách sử dụng Array.prototype.some()như dưới đây.

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

Tôi tin rằng cách tiếp cận này tốt hơn những cách khác. Đó là lý do tại sao tôi đăng câu trả lời này.

Cập nhật nhận xét của Sebastian Vittersø

Ở đây bạn cũng có thể sử dụng Array.prototype.every().

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

1
Thay vì sử dụng phủ định ở hai nơi ở đây, bạn có thể làm:test.every(value => typeof value === 'string')
— Sebastian

1
@ SebastianVittersø Cảm ơn đề xuất của NICE. Tôi đã cập nhật câu trả lời của mình.
— Sudarshana Dayananda

2

Thử đi:

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

6
Thay vì sao chép câu trả lời khác, vui lòng chỉ ra câu trả lời trùng lặp dưới dạng nhận xét, đặc biệt vì điều này không hoạt động trong mọi trường hợp.
— WiredPrairie

Điều này chỉ kiểm tra kiểu chính chứ không phải mọi con của Mảng.
— giovannipds

0

có một vấn đề nhỏ ở đây bởi vì

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

sẽ không dừng bước trước. Vì vậy, hàm sẽ trả về true ngay cả khi mảng không chứa giá trị chuỗi nào.

Điều này dường như khiến tôi băn khoăn:

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

Xin chào, Hans

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.