code: function refinement(name, type, predicate) {
    if (name[TYPICAL_TYPE]) {
      predicate = type;
      type = name;
      name = `${type.name}Refinement`;
    }
  
    /* istanbul ignore else */
    if (__DEV__) {
      assert(typeof name === 'string', `refinement()'s name must be a string`);
      assert(type[TYPICAL_TYPE], `refinement()'s type must a type`);
      assert(
        typeof predicate === 'function',
        `refinement()'s predicate must be a function`
      );
    }
  
    const api = this;
  
    function Refinement(value, context) {
      if (Context.isRequired(context)) {
        return Context.with(value, Refinement, context, api);
      }
  
      const result = type(value, context);
      if (context.isErrorWrapper(result)) {
        return result;
      } else if (predicate(result)) {
        return context.toValue(result, Refinement);
      } else {
        return context.valueIsNotOfType(result, Refinement);
      }
    }
  
    return decorate(Refinement, name, refinement, type, predicate);
  }
docs: /* ================================================================================
  Combinators that modify existing types
  ================================================================================