import "../Operator"
/**
 * Ported from https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/Has.scala
 *
 * Copyright 2020 Michael Arnaldi and the Matechs Garage Contributors.
 */
import type { Option } from "../Option"
/**
 * URI used in Has
 */
export declare const HasURI: unique symbol
/**
 * Has signal presence of a specific service provided via Tag in the environment
 */
export interface Has<T> {
  [HasURI]: {
    _T: () => T
  }
}
/**
 * Extract the type of a class constructor
 */
export declare type ConstructorType<K extends Constructor<any>> = K extends {
  prototype: infer T
}
  ? T
  : never
export declare type Constructor<T> = Function & {
  prototype: T
}
/**
 * Tag Encodes capabilities of reading and writing a service T into a generic environment
 */
export interface Tag<T> {
  _tag: "Tag"
  _T: T
  key: PropertyKey
  def: boolean
  overridable: () => Tag<T>
  fixed: () => Tag<T>
  refine: <T1 extends T>() => Tag<T1>
  read: (r: Has<T>) => T
  readOption: (r: unknown) => Option<T>
  setKey: (s: PropertyKey) => Tag<T>
  of: (_: T) => Has<T>
}
/**
 * Extract the Has type from any augumented variant
 */
export declare type HasTag<T> = [T] extends [Tag<infer A>] ? Has<A> : never
/**
 * Create a service entry Tag from a type and a URI
 */
export declare function tag<T extends Constructor<any>>(_: T): Tag<ConstructorType<T>>
export declare function tag<T>(): Tag<T>
/**
 * Get the service type of a Has
 */
export declare type ServiceType<T> = [T] extends [Has<infer A>] ? A : never
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */
export declare const replaceServiceIn: <T>(
  _: Tag<T>,
  f: (t: T) => T
) => <R>(r: R & Has<T>) => R & Has<T>
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */
export declare const replaceServiceIn_: <R, T>(
  r: R & Has<T>,
  _: Tag<T>,
  f: (t: T) => T
) => R & Has<T>
/**
 * Flags the current Has to be overridable, when this is used subsequently provided
 * environments will override pre-existing. Useful to provide defaults.
 */
export declare const overridable: <T>(h: Tag<T>) => Tag<T>
export declare function mergeEnvironments<T, R1>(_: Tag<T>, r: R1, t: T): R1 & Has<T>
export declare class DerivationContext {
  readonly hasMap: Map<Tag<any>, Tag<any>>
  derive<T, T2>(has: Tag<T>, f: () => Tag<T2>): Tag<T2>
}
//# sourceMappingURL=index.d.ts.map
