Skip to content

Commit

Permalink
basic optic
Browse files Browse the repository at this point in the history
  • Loading branch information
kwbauson committed Apr 12, 2021
1 parent 9d1793e commit 9e28ea8
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eval "$(nle direnv)"
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules/
node_modules
dist/
cache/
.cache/
89 changes: 88 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
@@ -1 +1,88 @@
console.log('foo')
export declare class Optic<S, A> {
static identity: Optic<unknown, unknown>

get: Fn<[S], A>
put: Fn<[S, A], S>

to<B>(get: Fn<[A], B>, put: Fn<[A, B], A>): Optic<S, B>
to<B>(optical: Optical<A, B>): Optic<S, B>

of<T>(get: Fn<[T], S>, put: Fn<[T, S], T>): Optic<T, A>
of<T>(optical: Optical<T, S>): Optic<T, A>

pick<KS extends (keyof A)[]>(keys: KS): Optic<S, Pick<A, KS[number]>>
omit<KS extends (keyof A)[]>(keys: KS): Optic<S, Omit<A, KS[number]>>

map<B>(optical: Optical<ValueType<A>, B>): Optic<S, B>

at<K extends keyof Record<A>>(key: K): Optic<S, Maybe<Record<A>[K]>>

choices: { [K in keyof Choice<S>]: Optic<Choice<S>[K], A> }
}

export type Optical<S, A> =
| Optic<S, A>
| Exclude<A, object | Function | Optic<any, any>>
| ((attrs: { [K in keyof A]: Optic<S, A[K]> }) => Optical<S, A>)
| { [K in keyof A]: Optical<S, A> }

export declare function optic<S>(): Optic<S, S>

export type Record<T> = keyof T extends never
? never
: Exclude<Extract<T, object>, Function>
export type Choice<T> = NotUnknown<Intersect<T extends any ? Single<T> : never>>
type Single<T> = ChoiceType<T> extends never
? Intersect<keyof T> extends never
? unknown
: T
: { [K in ChoiceType<T>]: undefined }
type ChoiceType<T> = string extends T
? never
: number extends T
? never
: symbol extends T
? never
: T extends keyof any
? T
: T extends true
? 'true'
: T extends false
? 'false'
: never

export type Fn<Args extends unknown[], Result> = (...args: Args) => Result
export type Maybe<T> = 'nothing' | { just: T }
export type Intersect<T> = (T extends any ? Fn<[T], void> : never) extends Fn<
[infer I],
void
>
? I
: never
export type ValueOf<T> = T[keyof T]
export type ValueType<T> = [T] extends [(infer U)[]]
? U
: [T] extends [{ [_ in any]: infer U }]
? U
: never
type NotUnknown<T> = [unknown] extends [T] ? never : T
export type Diff<T, U> = IfEq<keyof T, keyof U, {}, Omit<T, keyof U>>
export type Common<T, U> = Pick<T, Extract<keyof T, keyof U>>
type IfEq<T, U, A, B> = [T] extends [U] ? ([U] extends [T] ? A : B) : B

export type VNode =
| { Div: VNode[] }
| { Text: string }
| { Input: string }
| { Button: { label: string; clicked: boolean } }
| 'Break'
| 'Divider'

export const {
Div,
Text,
Input,
Button,
Break,
Divider,
} = optic<VNode>().choices

0 comments on commit 9e28ea8

Please sign in to comment.