【问题标题】:Test for array of string type in TypeScript在 TypeScript 中测试字符串类型的数组
【发布时间】:2014-06-01 13:21:37
【问题描述】:

如何在 TypeScript 中测试变量是否为字符串数组?像这样的:

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

编辑:我更新了文本以要求对 string[] 进行测试。这只是在之前的代码示例中。

【问题讨论】:

  • 由于 TypeScript 只是编译为 JavaScript,因此可以通过搜索 JavaScript 解决方案找到答案。此外,值得看看一些答案,因为答案取决于主机以及它是如何被使用和传递的。

标签: typescript


【解决方案1】:

试试这个:

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

【讨论】:

  • 与其复制另一个答案,不如指出重复的内容作为评论,尤其是因为这并非在所有情况下都有效。
  • 这只是检查主类型而不是每个 Array 的子类型。
【解决方案2】:

在一般情况下,您无法测试 string[],但您可以像在 JavaScript 中一样轻松地测试 Array https://stackoverflow.com/a/767492/390330(我更喜欢 Array.isArray(value))。

如果您特别想要 string 数组,您可以执行以下操作:

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

如果您需要检查一个类的数组(不是基本类型)

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

如果您不确定所有项目都是同一类型

items.every(it => it instanceof MyClassName)

【讨论】:

  • instanceof Array 跨帧检查数组时失败。首选Array.isArraytwitter.com/mgechev/status/1292709820873748480
  • @axmrnv 完全同意?
  • 另外,您可以在告诉 somethingIsNotString 之后立即中断循环。使用您的代码,它必然会遍历所有整个数组,这不是必需的。
  • @Kukuster value.some() 可以使用,但答案与如何确定数组/非数组无关
【解决方案3】:

另一个选项是Array.isArray()

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

【讨论】:

  • 但这不会检查类型为string的元素。
  • 是的。然后你需要额外的检查。 Array.isArray(classNames) && classNames.every(it => typeof it === 'string')
  • @grigson 检查 400 多个结果时的性能如何?我应该不考虑这种类型检查,只检查第一个孩子还是使用这种“所有”东西安全吗?
  • @giovannipds 请查看asmironov's answer
【解决方案4】:

我知道这个问题已经得到解答,但是 TypeScript 引入了类型保护:https://www.typescriptlang.org/docs/handbook/advanced-types.html#typeof-type-guards

如果你有一个像这样的类型:Object[] | string[] 并且根据它的类型有条件地做什么 - 你可以使用这种类型保护:

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

空数组输入为string[] 存在问题,但这可能没问题

【讨论】:

  • forEach 中的return false 无效。
  • @Ishtar 我已经更正了
  • 在我看来,您实现 array.every(it => typeof it === 'string') 的方式不是很好
【解决方案5】:

这里有个小问题,因为

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

不会停止 foreach。 因此,即使数组不包含任何字符串值,该函数也会返回 true。

这对我来说似乎很不错:

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

你好,汉斯

【讨论】:

    【解决方案6】:

    这是迄今为止最简洁的解决方案:

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

    请注意,value.every 将为空数组返回 true。如果需要为空数组返回false,则应在条件子句中添加value.length

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

    TypeScript 中没有任何运行时类型信息(也不会有,参见TypeScript Design Goals > Non goals, 5),因此无法获取空数组的类型。对于一个非空数组,你所能做的就是一个一个地检查它的元素的类型。

    【讨论】:

    • 请注意,如果数组为空,您需要检查 value.length>0 而不仅仅是 value.length,因为这将返回 0
    • @markyph, 0 是 JS/TS 中的假值,在这种情况下被解释为假。
    • 是的,我知道 0 是假的 - 但上面打破了我的测试,正如预期的那样它是“假”但返回 0 - value.length>0 保证它是假的
    【解决方案7】:

    您可以使用Array.prototype.some() 轻松完成,如下所示。

    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
    

    我相信这种方法比其他方法更好。这就是我发布此答案的原因。

    Sebastian Vittersø 的评论更新

    这里你也可以使用Array.prototype.every()

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

    【讨论】:

    • 这里不是在两个地方使用否定,而是:test.every(value =&gt; typeof value === 'string')
    • @SebastianVittersø 感谢 NICE 的建议。我更新了我的答案。
    猜你喜欢
    • 2017-11-13
    • 2022-01-18
    • 2019-02-09
    • 2020-12-11
    • 2019-01-02
    • 2015-02-07
    • 2019-02-04
    • 1970-01-01
    • 2021-05-25
    相关资源
    最近更新 更多