Skip to content

Instantly share code, notes, and snippets.

@SimonMeskens
Created April 19, 2018 01:23
Show Gist options
  • Save SimonMeskens/efa1e8c133bc48966a3ea47e8089d4a9 to your computer and use it in GitHub Desktop.
Save SimonMeskens/efa1e8c133bc48966a3ea47e8089d4a9 to your computer and use it in GitHub Desktop.
TypeProps
import { Option } from "./option";
import { Generic, TypeParams } from "typeprops";
interface Functor<F> {
map: <T>(
this: Generic<F>,
f: (a: TypeParams<F>[0]) => T
) => Generic<F, [T]>;
}
const test = <F extends Functor<F>>(
mappable: F,
transform: (a: TypeParams<F>[0]) => string
) => {
return mappable.map(transform);
};
const option = Option.of(4);
test(option, (x: number) => "test");
declare module "typeprops" {
const OptionId: unique symbol;
interface TypeProps<Type, Params extends Tuple = never> {
[OptionId]: {
id: Type extends Option<any> ? typeof OptionId : never;
parameters: Type extends Option<infer A> ? [A] : never;
type: Option<Params[0]>;
};
}
}
export interface Some<T> {
value: T;
map: <U = T>(this: Some<T>, f: (a: T) => U) => Some<U>;
extract: (this: Some<T>) => T;
}
export interface None {
map: (this: None, f: (a: any) => any) => None;
}
export interface Option<T> {
map: <U = T>(f: (a: T) => U) => Option<U>;
}
export const Option = {
of: <T>(a: T | undefined): Option<T> => (a === undefined ? none : some(a)),
empty: (): None => none
};
export const some: <T>(a: T) => Some<T> = <T>(a: T) => {
if (a === undefined) throw new TypeError('"a" is undefined');
return {
value: a,
map<U>(this: Some<T>, f: (a: T) => U) {
return some(f(this.value));
},
extract(this: Some<T>) {
return this.value;
}
};
};
export const none: None = {
map() {
return none;
}
};
declare module "typeprops" {
interface TypeProps<Type, Params extends Tuple = never> {}
type NeverProp = {
never: {
id: "never";
parameters: never;
type: never;
};
};
type TypeId<T> = (TypeProps<T> & NeverProp)[
| keyof TypeProps<T>
| "never"]["id"];
type TypeProp<T, Params extends Tuple = TypeParams<T>> = (TypeProps<
T,
Params
> &
NeverProp)[TypeId<T>];
type TypeParams<T> = (TypeProps<T> & NeverProp)[TypeId<T>]["parameters"];
type Generic<T, Params extends Tuple = TypeParams<T>> = TypeProp<
T,
Params
>["type"];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment