Skip to content
English

步骤执行、同步约束和停止顺序 ​

策略的具体实现如下。

ts
export function defineNormalization<Value, Context = void>(
  definitions: readonly NormalizationStep<Value, Context>[],
  options: NormalizationOptions<Value, Context> = {},
) {
  const isComplete = options.isComplete?.bind(options);
  const predicate = (value: unknown) =>
    booleanResult(
      value,
      'Normalization predicates must be synchronous',
      'Normalization predicates must return boolean',
    );
  const ids = new Set<string>();
  const steps = Object.freeze(
    definitions.map((step) => {
      breakWhile([
        {
          occur: () => !step.id.trim() || ids.has(step.id),
          error: 'Invalid or duplicate normalization step',
          tags: ['id'],
        },
        {
          occur: () => typeof step.normalize !== 'function',
          error: 'Missing normalization handler',
          tags: ['handler'],
        },
      ]);
      ids.add(step.id);
      return Object.freeze({
        id: step.id,
        when: step.when?.bind(step),
        normalize: step.normalize.bind(step),
      });
    }),
  );
  return Object.freeze({
    steps,
    normalize(value: Value, context: Context): Value {
      for (const step of steps) {
        if (step.when && !predicate(step.when(value, context))) continue;
        value = synchronous(
          step.normalize(value, context),
          'Normalization handlers must be synchronous',
        );
        if (isComplete && predicate(isComplete(value, context))) break;
      }
      return value;
    },
  });
}

export function uniqueBy<Value, Key>(
  values: readonly Value[],
  key: (value: Value) => Key,
  initial: Iterable<Key> = [],
): Value[] {
  const seen = new Set(initial);
  return values.filter((value) => {
    const id = key(value);
    if (seen.has(id)) return false;
    seen.add(id);
    return true;
  });
}

接口参考、使用示例与开发指南。