问题描述
我正在用 TypeScript 中的 Ramda 编写一个 Redux 选择器:
const getAvatar = pipe(
getCurrentUsersProfile,propOr('/images/default-avatar.png','avatar'),);
使用 prop
函数,我可以断言这样的返回类型:
const getCurrentUsersId = pipe(
getUserProfileSlice,prop<'currentUsersId'>('currentUsersId'),);
我怎样才能知道 propOr
总是返回一个 string
?
解决方法
您可以显式键入 propOr
调用,并添加返回值 (stackblitz):
import { pipe,propOr } from 'ramda';
const getCurrentUsersProfile = () => {};
const getAvatar = pipe(
getCurrentUsersProfile,propOr('/images/default-avatar.png','avatar') as (src: any) => string,);
,
我认为 propOr
从根本上很难输入——我认为说它总是返回一个字符串会破坏函数的意义。
该函数旨在在提供的对象不具有指定属性的情况下提供回退。对象的类型将满足以下三个条件之一:
- TS 可以验证它是否拥有该属性
- TS 可以验证它没有属性
- TS 无法验证是否拥有该属性
在第一个或第二个条件中,TS 可以告诉您函数结果的类型,因此调用 propOr 几乎没有意义——我们已经知道它要么有,要么没有我们正在查询的属性。
问题在于输入第三个条件。如果我们在一个未知类型的对象上调用 propOr,propOr 应该返回什么类型?充其量我想它是像 unknown | T
这样的东西,它什么也不告诉我们,真的。如果我们无法验证对象在某个属性 T
处是否具有类型为 K
的值,那么我们就无法确定函数的结果是什么。
我能想到的最好的事情(我希望有人有更好的建议)是提供一个函数,该函数将始终将键值强制转换为我们想要的类型,例如在以下示例中(请原谅非柯里化函数):
const hasKey = <K extends PropertyKey,T,U extends Record<K,U>>(k: K,o: any): o is U => o.hasOwnProperty(k);
const propOr = <K extends PropertyKey,T>(d: T,k: K,o: any,f: (x: any) => T) => hasKey(k,o)
? f(o[k])
: f(d);
const test = propOr<'avatar',string>('/images/default-avatar.png','avatar',{ a: 1 },(s: any) => `${s}`);
在这个例子中,test
是字符串类型,但是感觉很笨重。我想不出任何其他方法可以使用可靠的类型来做到这一点。 @OriDriori 提供类型提示的选项可以正常工作,但我猜它有点强迫打字稿的手 - propOr 可能 不返回字符串并说它总是不完全正确(尽管您可能完全乐意为您的代码接受这一点。