You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于fp-ts的Option<string>数组转string数组及SVG路径命令验证类型优化问题问询

问题2:修复validationErrors的类型并优化fp-ts验证代码

先看你代码里的核心问题:当前validationErrors被推断为(string | undefined)[],是因为你用了option.fold(() => undefined, some => some)——虽然你已经过滤了Some项,但fold的返回类型还是包含undefined。我们可以通过更精准的类型缩小来解决这个问题,同时优化代码:

1. 修复validationErrors的类型

直接在过滤Some项后,用option.get提取值即可,因为此时数组内的元素已经都是Some<string>,TypeScript能准确推断出类型:

import * as option from 'fp-ts/Option';
import * as fpArray from 'fp-ts/Array';
import * as either from 'fp-ts/Either';
import * as fpFunction from 'fp-ts/function';

// ... 你的Command、CommandArray等类型定义

type CommandValidation = (commands: CommandArray, nextCommand: Command) => option.Option<string>;
const newCommandValidations: CommandValidation[] = [ 
  validateFirstCommandIsMove, 
  validateSymmetricCommandFollowsBezier, 
  validateNoMoveAfterMove 
];

export const safelyPushCommand = (command: Command) => either.chain((commands: CommandArray) => {
  const validationErrors: string[] = fpFunction.pipe(
    newCommandValidations,
    fpArray.map(validation => validation(commands, command)),
    // 过滤后,数组元素类型缩小为Some<string>[]
    fpArray.filter(option.isSome),
    // 直接提取Some的值,得到明确的string[]
    fpArray.map(option.get)
  );

  return validationErrors.length > 0 
    ? either.left(validationErrors) 
    : either.right(pushCommands([command])(commands));
});

另外注意:你原来用了either.map,但回调函数返回的是Either类型,这会导致最终类型变成Either<E, Either<string[], CommandArray>>(嵌套的Either),所以应该换成either.chain,它会自动扁平化嵌套的Either结构。

2. 是否需要用apply函数传递参数?

当前的写法已经很清晰,不是必须用apply。但如果你想让验证函数更符合函数式组合的风格,可以将其柯里化:

// 改为柯里化的验证函数类型
type CommandValidation = (commands: CommandArray) => (nextCommand: Command) => option.Option<string>;

// 然后可以用apply来批量传递commands参数
const validationErrors: string[] = fpFunction.pipe(
  newCommandValidations,
  // 给所有验证函数传入commands参数,得到(nextCommand) => Option<string>的数组
  fpArray.map(fpFunction.apply(commands)),
  // 传入command参数,得到Option<string>的数组
  fpArray.map(validate => validate(command)),
  fpArray.filter(option.isSome),
  fpArray.map(option.get)
);

这种写法更偏向函数式风格,但可读性因人而异,你可以根据自己的习惯选择。

3. 当fold的第二个参数是恒等函数时的简洁写法

如果是处理单个Option(且可能为None),当fold的第二个参数是恒等函数时,确实可以用更简洁的option.toUndefined或option.getOrElse(() => undefined)来替代,它们的效果和你写的fold完全一致。但在我们这个场景下,因为已经过滤了Some项,所以直接用option.get是最直接高效的——既不需要处理None分支,又能得到明确的类型。


内容的提问来源于stack exchange,提问作者J. Barca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:19:07