TypeScript Ramda propOr return 类型

TypeScript Ramda propOr return type

我正在使用 TypeScript 中的 Ramda 编写 Redux 选择器:

const getAvatar = pipe(
  getCurrentUsersProfile,
  propOr('/images/default-avatar.png', 'avatar'),
);

getAvatar 的工具提示说 returns unknown

使用 prop 函数,我可以断言一个 return 类型,如下所示:

const getCurrentUsersId = pipe(
  getUserProfileSlice,
  prop<'currentUsersId'>('currentUsersId'),
);

我如何让它知道 propOr 总是 return 是 string

您可以显式键入 propOr 调用,并添加 return 值 (stackblitz):

import { pipe, propOr } from 'ramda';

const getCurrentUsersProfile = () => {};

const getAvatar = pipe(
  getCurrentUsersProfile,
  propOr('/images/default-avatar.png', 'avatar') as (src: any) => string,
);

propOr 是,我认为,从根本上说很难打字 - 说它总是 return 是一个字符串,我认为,这会打败函数的意义。

该函数旨在在提供的对象没有指定的 属性 的情况下提供回退。对象的类型将满足三个条件之一:

  • TS 可以验证它具有 属性
  • TS 可以验证它没有 属性
  • TS 无法验证是否有 属性

在第一种或第二种情况下,TS 可以告诉您函数结果的类型,因此调用 propOr 几乎没有意义 - 我们已经知道它可以或不可以有我们正在查询的属性。

问题在于第三个条件的输入。如果我们在未知类型的对象上调用 propOr,那么 propOr return 应该是什么类型?充其量我认为它是 unknown | T 之类的东西,它实际上什么也没告诉我们。如果我们无法验证该对象在某些 属性 K 处将具有类型 T 的值,那么我们无法说出该函数的结果是什么。

我能想到的最好的事情(我希望有人有更好的建议)是提供一个函数,它总是将键的值强制转换为我们想要的类型,例如在下面的例子中(原谅未柯里化的函数):

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 may not return a string 并说它总是会是不完全正确(尽管您可能非常乐意接受您的代码实际上会接受这一点)。