Created
April 19, 2018 01:23
-
-
Save SimonMeskens/efa1e8c133bc48966a3ea47e8089d4a9 to your computer and use it in GitHub Desktop.
TypeProps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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