bounty还有2天到期。回答此问题可获得+250声望奖励。Evanss希望引起更多关注这个问题。
有没有办法将TypeScript类型安全添加到Lodash的set函数中?
我需要在深度嵌套的对象上设置值。属性可以是未定义的,我不想覆盖其他对象属性。
这段代码的工作原理:
import set from "lodash/set";
type Res = {
position?: {
top?: { value: number },
right?: { value: number }
},
color?: {
red?: number,
blue?: number
}
};
const res : Res = {};
const items = ["p-top-1", "p-right-2", 'c-red-300'];
for (let i = 0; i < items.length; i++) {
const item = items[i];
const [type, key, value] = item.split('-');
if(type === 'p') {
set(res, `position.${key}.value`, value);
}
if(type === 'c') {
set(res, `color.${key}.value`, value);
}
}
但它没有类型安全,例如这不会出错:
if(type === 'p') {
set(res, `whatever-key-here.${key}.value`, value);
}
3条答案
按热度按时间blmhpbnm1#
在
moderndash
中有类似的函数set
,但它缺少一个类型安全的set-existing-value
对应函数(it工作原理与
lodash
的set
完全相同,因此您可以自由地使用import { set as setUntyped } from "lodash"
)通过将其类型修改为a-la-
set
而不是a-la-assign
,可以直接实现set
的类型安全版本:要将它用于拆分字符串,还需要
string.split
重载:然后示例代码显示错误,正如预期的那样:Playground:https://tsplay.dev/Nn886W
vwhgwdsa2#
首先,我们需要得到我们可以得到的可能路径。我们将使用mapped types。我们需要一些utils:
Dot
-连接到一个路径的字符串:DefaultStopTypes
-我们应该停止深入研究的类型PathsToFields
-接受对象和停止类型。递归遍历对象并获取其字段的路径,并使用点表示法。示例:
GetPropertyType
-接受一个对象的字段路径。返回给定路径下属性的类型:剩下的部分是编写
set
函数,这很简单:用途:
然而,在您的情况下,这是不够的,因为您使用的是实用类,例如'p-top-1',并且split不是类型化的,所以您必须使用
as
Assert来Assert正确的类型。我可以建议增加以下类型:
重新申报项目如下:
这仍然不是解决方案,因为拆分将返回一个
string[]
。让我们为拆分创建一个实用程序类型,它返回确切的值类型:示例:
就是这样,尽管你必须将
value
Assert为number
,因为当你拆分的时候你会得到一个string
。Playground
ssgvzors3#
你是对的,lodash的set函数不能很好地与TypeScript的静态类型检查一起使用。TypeScript是一种静态类型语言,lodash的set函数本质上是动态的。这意味着lodash的set函数中使用的属性路径是一个字符串,可以是任何东西,所以TypeScript在编译时无法检查它。
在这里添加一些类型安全性的一种方法是将可以与lodash的set函数一起使用的属性限制为在您的类型中定义的属性。这并不能完全解决问题,但至少可以限制问题的范围。
例如,我们可以使用TypeScript的keyof和conditional类型来帮助我们。让我们定义一个helper函数:
在本例中,如果您使用的任何属性键未在PositionKeys或ColorKeys类型中定义,TypeScript将给予编译时错误。这不是一个完美的解决方案,但它确实增加了安全性。
请注意,TypeScript仍然无法验证传递给lodash的set函数的属性路径字符串的正确性。你可以传递一个错误的属性路径,比如'position.notExistingProp.value',TypeScript将无法捕获该错误。