判断传入参数是否是数组类型的方法
大约 4 分钟
使用 TypeScript 实现判断数组类型的方法
在 TypeScript 中,有多种方式可以实现判断传入参数是否为数组类型的方法。以下是几种不同的实现方式:
1. 基础实现 - 使用 instanceof
function isArray(value: any): boolean {
return value instanceof Array;
}
// 使用示例
console.log(isArray([1, 2, 3])); // true
console.log(isArray("hello")); // false
console.log(isArray({})); // false
console.log(isArray(null)); // false2. 使用 Array.isArray()(推荐)
function isArray(value: any): value is any[] {
return Array.isArray(value);
}
// 使用示例
console.log(isArray([1, 2, 3])); // true
console.log(isArray("hello")); // false
console.log(isArray({})); // false
// 在类型守卫上下文中使用
function processValue(value: string | number | any[]) {
if (isArray(value)) {
// TypeScript 知道这里 value 是数组类型
console.log(`Array length: ${value.length}`);
value.forEach(item => console.log(item));
} else {
console.log(`Not an array: ${value}`);
}
}3. 泛型版本 - 判断特定类型数组
// 判断是否为特定类型的数组
function isTypedArray<T>(value: any, typeGuard: (item: any) => item is T): value is T[] {
return Array.isArray(value) && value.every(typeGuard);
}
// 类型守卫函数
function isString(value: any): value is string {
return typeof value === 'string';
}
function isNumber(value: any): value is number {
return typeof value === 'number';
}
// 使用示例
console.log(isTypedArray(["a", "b", "c"], isString)); // true
console.log(isTypedArray([1, 2, 3], isNumber)); // true
console.log(isTypedArray([1, "b", 3], isNumber)); // false4. 更完整的数组类型判断类
class ArrayChecker {
// 基础数组判断
static isArray(value: any): value is any[] {
return Array.isArray(value);
}
// 判断是否为空数组
static isEmptyArray(value: any): value is [] {
return Array.isArray(value) && value.length === 0;
}
// 判断是否为非空数组
static isNonEmptyArray<T>(value: T[] | any): value is T[] {
return Array.isArray(value) && value.length > 0;
}
// 判断是否为特定类型数组
static isTypedArray<T>(value: any, typeGuard: (item: any) => item is T): value is T[] {
return Array.isArray(value) && value.every(typeGuard);
}
// 判断是否为字符串数组
static isStringArray(value: any): value is string[] {
return this.isTypedArray(value, (item): item is string => typeof item === 'string');
}
// 判断是否为数字数组
static isNumberArray(value: any): value is number[] {
return this.isTypedArray(value, (item): item is number => typeof item === 'number');
}
// 判断是否为对象数组
static isObjectArray(value: any): value is object[] {
return this.isTypedArray(value, (item): item is object =>
typeof item === 'object' && item !== null && !Array.isArray(item));
}
}
// 使用示例
console.log(ArrayChecker.isArray([1, 2, 3])); // true
console.log(ArrayChecker.isEmptyArray([])); // true
console.log(ArrayChecker.isNonEmptyArray([1, 2, 3])); // true
console.log(ArrayChecker.isStringArray(["a", "b"])); // true
console.log(ArrayChecker.isNumberArray([1, 2, 3])); // true
console.log(ArrayChecker.isObjectArray([{}, {a: 1}])); // true5. 使用类型谓词的高级实现
// 更精确的类型谓词
function isArrayOfType<T>(value: any, expectedType: string): value is T[] {
if (!Array.isArray(value)) {
return false;
}
return value.every(item => {
if (expectedType === 'string') return typeof item === 'string';
if (expectedType === 'number') return typeof item === 'number';
if (expectedType === 'boolean') return typeof item === 'boolean';
if (expectedType === 'object') return typeof item === 'object' && item !== null;
return typeof item === expectedType;
});
}
// 使用示例
const stringArray = ["hello", "world"];
const mixedArray = ["hello", 123];
if (isArrayOfType<string>(stringArray, 'string')) {
// TypeScript 知道这是 string[] 类型
console.log(`All items are strings: ${stringArray.join(', ')}`);
}
if (!isArrayOfType<string>(mixedArray, 'string')) {
console.log('Array contains non-string elements');
}6. 支持只读数组的实现
// 支持只读数组的类型守卫
function isReadonlyArray<T>(value: any): value is readonly T[] {
return Array.isArray(value);
}
function isMutableArray<T>(value: any): value is T[] {
return Array.isArray(value);
}
// 使用示例
const readonlyArr: readonly string[] = ["a", "b", "c"] as const;
const mutableArr: string[] = ["x", "y", "z"];
console.log(isReadonlyArray(readonlyArr)); // true
console.log(isMutableArray(mutableArr)); // true7. 完整的实用工具集
namespace ArrayUtils {
// 基础判断
export function isArray(value: any): value is any[] {
return Array.isArray(value);
}
// 深度判断(检查多维数组)
export function isNestedArray(value: any): value is any[][] {
return Array.isArray(value) && value.every(item => Array.isArray(item));
}
// 判断数组维度
export function getArrayDepth(arr: any): number {
return Array.isArray(arr)
? 1 + Math.max(0, ...arr.map(getArrayDepth))
: 0;
}
// 类型安全的数组检查
export function validateArray<T>(
value: any,
elementValidator: (item: any) => item is T
): value is T[] {
return Array.isArray(value) && value.every(elementValidator);
}
// 检查数组是否包含特定类型元素
export function hasTypeElements<T>(
arr: any[],
typeGuard: (item: any) => item is T
): arr is (T | unknown)[] {
return arr.some(typeGuard);
}
}
// 使用示例
const testArray = [1, 2, 3];
const nestedArray = [[1, 2], [3, 4]];
const mixedArray = [1, "hello", true];
console.log(ArrayUtils.isArray(testArray)); // true
console.log(ArrayUtils.isNestedArray(nestedArray)); // true
console.log(ArrayUtils.getArrayDepth(nestedArray)); // 2
console.log(ArrayUtils.validateArray(testArray, (item): item is number => typeof item === 'number')); // true
console.log(ArrayUtils.hasTypeElements(mixedArray, (item): item is string => typeof item === 'string')); // true8. 实际应用场景
// 处理API响应数据
interface ApiResponse {
data: any;
status: number;
}
function processApiResponse(response: ApiResponse): void {
if (ArrayUtils.isArray(response.data)) {
// 安全地处理数组数据
console.log(`Received ${response.data.length} items`);
response.data.forEach((item, index) => {
console.log(`Item ${index}:`, item);
});
} else {
console.log('Response data is not an array');
}
}
// 数据验证场景
function validateUserData(input: any): input is string[] {
return ArrayUtils.validateArray(input, (item): item is string => typeof item === 'string');
}
// 使用
const userData = ["Alice", "Bob", "Charlie"];
if (validateUserData(userData)) {
// TypeScript 知道 userData 是 string[] 类型
console.log(`Users: ${userData.join(', ')}`);
}总结
以上实现方式各有特点:
- 基础实现:简单直接,适合基本需求
- 类型谓词版本:提供更好的类型安全性
- 泛型版本:更加灵活,支持特定类型数组判断
- 工具类版本:功能丰富,适合复杂场景
- 命名空间版本:组织良好,便于维护
推荐在实际项目中使用 Array.isArray() 结合类型谓词的方式,这样既保证了运行时的正确性,又获得了编译时的类型安全。