带有 Lodash 的 TypeScript:_.map(["123", " 234 "], _.trim) 返回 boolean[]?
Posted
技术标签:
【中文标题】带有 Lodash 的 TypeScript:_.map(["123", " 234 "], _.trim) 返回 boolean[]?【英文标题】:TypeScript with Lodash: _.map(["123", " 234 "], _.trim) returns boolean[]? 【发布时间】:2017-11-12 01:27:56 【问题描述】:我有一个字符串数组,它们被分割成这样:
var searchValue = "600-800, 123, 180";
var groups = searchValue.split(","); // => ["600-800", " 123", " 180"]
(因此项目周围可能存在空格),我想删除空格。我知道我可以使用 Array.prototype.map
和 String.prototype.trim
,但我想要一个专门使用 Lodash 的解决方案。
According to the docs,我应该可以说:_.map([' foo ', ' bar '], _.trim);
,它会返回['foo', 'bar']
,即string[]
。
但是,TypeScript 对我大吼大叫。这是我在编辑器中看到的内容。
我正在运行 TypeScript 2.3.2 和 Lodash 4.17.4
奇怪的是,如果我说:
var values:string[] = _.map([' foo ', ' bar '], String.prototype.trim);
TypeScript 错误消失了,但是当searchValue
为空并且groups
返回[""]
时出现以下运行时错误:
TypeError: String.prototype.trim 在 null 或 undefined 上调用
我尝试过的事情:
var values:string[] = _.map(_.filter(groups, group => group.indexOf("-") === -1), _.trim);
var values:string[] = _.map(_.filter(groups, function (group) return group.indexOf("-") === -1; ), _.trim);
var values:string[] = _.map<string, (string?: string, chars?: string) => string>(_.filter(groups, function (group) return group.indexOf("-") === -1 ), _.trim);
var values:string[] = _.map<string, (string?: string, chars?: string) => string[]>(_.filter(groups, function (group) return group.indexOf("-") === -1 ), _.trim);
var values:string[] = _.map<string, (string: string, chars: string) => string>(_.filter(groups, function (group) return group.indexOf("-") === -1 ), _.trim);
var values:string[] = _.map<string, (string: string) => string>(_.filter(groups, function (group) return group.indexOf("-") === -1 ), _.trim);
一切都无济于事。我很茫然。我在这里做错了什么还是这可能是 Lodash/TypeScript 错误?
【问题讨论】:
【参考方案1】:以下变体似乎有效:
let values: string[] = _.map([' foo ', ' bar '], str => _.trim(str))
这是我对为什么会发生这种情况的猜测。 map
有很多重载,你想定位这个:
map<T, TResult>(
collection: List<T> | null | undefined,
iteratee: ListIterator<T, TResult>
): TResult[];
其中ListIterator
定义为:
type ListIterator<T, TResult> = (value: T, index: number, collection: List<T>) => TResult;
因此,您希望修剪功能与上述ListIterator
的定义相匹配。但是trim
实际上定义为:
trim(
string?: string,
chars?: string
): string;
所以当你执行以下操作时:
let values: string[] = _.map([' foo ', ' bar '], _.trim);
您实际上最终会遇到不同的过载,其定义为:
map<T, TObject extends >(
collection: List<T>|Dictionary<T>|NumericDictionary<T> | null | undefined,
iteratee?: TObject
): boolean[];
所以当你切换到以下变体时:
let values: string[] = _.map([' foo ', ' bar '], str => _.trim(str))
您的修剪函数str => _trim(str)
符合ListIterator
,即使它省略了最后两个参数(index
和collection
)。
【讨论】:
很好的解释,这是有道理的。我会在星期一早上首先尝试它,如果它最终对我有用,则标记为已接受。仍然好奇为什么文档会给出他们给出的例子。看起来很奇怪,不是吗? 他们给出的示例使用纯 javascript。但是后来添加了类型定义以在使用 TypeScript 时提供帮助,因此有时您必须更加具体。请注意trim
的第一个参数定义为string
,而ListIterator
的第一个参数定义为泛型类型T
,在您的情况下是string
,因为您有一个string
数组.因此,如果您在纯动态 JavaScript 中运行他们的示例,它会起作用,因为只使用了第一个参数。但是在使用 TypeScript 时必须更加具体,因为它会检查所有参数。【参考方案2】:
问题是_.trim
可以接受两个参数:
trim(string?: string, chars?: string): string;
这与 lodash 的 ListIterator
类型不兼容,其中第二个参数(如果存在)是一个数字(索引)。
因此,编译器正在回退到 _.map
函数的不同类型,这是一个模糊的函数,它将一个对象作为迭代对象并返回一个布尔数组(“对于给定对象的属性的元素返回 true,否则为假。”)
Frank Modica 的回答给出了正确的解决方案。
【讨论】:
感谢您的解释,这很有帮助。让我想知道为什么这些文档会给出他们给出的例子 - 看起来很奇怪,不是吗?以上是关于带有 Lodash 的 TypeScript:_.map(["123", " 234 "], _.trim) 返回 boolean[]?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 TypeScript 中重新导出单个 lodash 模块
[TypeScript] Type Definitions and Modules
[TypeScript] Using Lodash in TypeScript with Typings and SystemJS