Skip to content

Experiments with Type module #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 137 additions & 39 deletions src/Core__Type.mjs
Original file line number Diff line number Diff line change
@@ -1,53 +1,151 @@
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as Caml_option from "rescript/lib/es6/caml_option.js";

var isNull = (function(a) { return (a===null); });

var isNullOrUndefined = (function(a) { return (a===null || a===undefined); });

var isUndefined = (function(a) { return (a===undefined); });

function classify(value) {
var match = Object.prototype.toString.call(value);
switch (match) {
case "[object Boolean]" :
return {
TAG: /* Bool */0,
_0: value
};
case "[object AsyncFunction]" :
case "[object Function]" :
case "[object GeneratorFunction]" :
return {
TAG: /* Function */4,
_0: value
};
case "[object Null]" :
return /* Null */0;
case "[object Number]" :
return {
TAG: /* Number */2,
_0: value
};
case "[object String]" :
return {
TAG: /* String */1,
_0: value
};
case "[object Symbol]" :
return {
TAG: /* Symbol */5,
_0: value
};
case "[object Undefined]" :
return /* Undefined */1;
default:
var match = typeof value;
if (match === "symbol") {
return {
TAG: /* Symbol */5,
_0: value
};
} else if (match === "boolean") {
return {
TAG: /* Bool */1,
_0: value
};
} else if (match === "string") {
return {
TAG: /* String */4,
_0: value
};
} else if (match === "function") {
return {
TAG: /* Function */6,
_0: value
};
} else if (match === "object") {
if (isNull(value)) {
return /* Null */1;
} else {
return {
TAG: /* Object */3,
TAG: /* Object */0,
_0: value
};
}
} else if (match === "undefined") {
return /* Undefined */0;
} else if (match === "number") {
return {
TAG: /* Number */2,
_0: value
};
} else {
return {
TAG: /* BigInt */3,
_0: value
};
}
}

function toObject(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* Object */0) {
return ;
} else {
return Caml_option.some(i$1._0);
}
}

function toBool(i) {
var b = classify(i);
if (typeof b === "number" || b.TAG !== /* Bool */1) {
return ;
} else {
return b._0;
}
}

function toFloat(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* Number */2) {
return ;
} else {
return i$1._0;
}
}

function toBigInt(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* BigInt */3) {
return ;
} else {
return Caml_option.some(i$1._0);
}
}

var Classify = {
classify: classify
};
function toString(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* String */4) {
return ;
} else {
return i$1._0;
}
}

function toSymbol(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* Symbol */5) {
return ;
} else {
return Caml_option.some(i$1._0);
}
}

function toFunction(i) {
var i$1 = classify(i);
if (typeof i$1 === "number" || i$1.TAG !== /* Function */6) {
return ;
} else {
return Caml_option.some(i$1._0);
}
}

function get(item, name) {
if (isNullOrUndefined(item)) {
return ;
} else {
return item[name];
}
}

function getBySymbol(item, sym) {
if (isNullOrUndefined(item)) {
return ;
} else {
return item[sym];
}
}

export {
Classify ,
classify ,
isUndefined ,
isNull ,
isNullOrUndefined ,
toObject ,
toBool ,
toFloat ,
toBigInt ,
toString ,
toSymbol ,
toFunction ,
get ,
getBySymbol ,
}
/* No side effect */
146 changes: 106 additions & 40 deletions src/Core__Type.res
Original file line number Diff line number Diff line change
@@ -1,43 +1,109 @@
type t = [#undefined | #object | #boolean | #number | #bigint | #string | #symbol | #function]

external typeof: 'a => t = "#typeof"

module Classify = {
type function
type object
type symbol

type t =
| Bool(bool)
| Null
| Undefined
| String(string)
| Number(float)
| Object(object)
| Function(function)
| Symbol(symbol)

@val external _internalClass: 'a => string = "Object.prototype.toString.call"
external _asBool: 'a => bool = "%identity"
external _asString: 'a => string = "%identity"
external _asFloat: 'a => float = "%identity"
external _asObject: 'a => object = "%identity"
external _asFunction: 'a => function = "%identity"
external _asSymbol: 'a => symbol = "%identity"

let classify = value => {
switch _internalClass(value) {
| "[object Boolean]" => Bool(_asBool(value))
| "[object Null]" => Null
| "[object Undefined]" => Undefined
| "[object String]" => String(_asString(value))
| "[object Number]" => Number(_asFloat(value))
| "[object Function]"
| "[object GeneratorFunction]"
| "[object AsyncFunction]" =>
Function(_asFunction(value))
| "[object Symbol]" => Symbol(_asSymbol(value))
| _ => Object(_asObject(value))
type typeof = [
| #undefined
| #object
| #boolean
| #number
| #bigint
| #string
| #symbol
| #function
]

external typeof: 'a => typeof = "#typeof"

type unknown
external toUnknown: 'a => unknown = "%identity"

type object // How to use with the Object module?
type function

// typeof null == "object". Gotta love that! Do better here.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#typeof_null
type jsType =
| Undefined
| Null
| Object(object)
| Bool(bool)
| Number(float)
| BigInt(Core__BigInt.t)
| String(string)
| Symbol(Core__Symbol.t)
| Function(function)

external toObjectUnsafe: 'a => object = "%identity"
external toBoolUnsafe: 'a => bool = "%identity"
external toFloatUnsafe: 'a => float = "%identity"
external toBigIntUnsafe: 'a => Core__BigInt.t = "%identity"
external toStringUnsafe: 'a => string = "%identity"
external toSymbolUnsafe: 'a => Core__Symbol.t = "%identity"
external toFunctionUnsafe: 'a => function = "%identity"

let isNull = %raw(`function(a) { return (a===null); }`)
let isNullOrUndefined = %raw(`function(a) { return (a===null || a===undefined); }`)
let isUndefined = %raw(`function(a) { return (a===undefined); }`)

let classify = value => {
switch typeof(value) {
| #number => value->toFloatUnsafe->Number
| #string => value->toStringUnsafe->String
| #boolean => value->toBoolUnsafe->Bool
| #undefined => Undefined
| #function => value->toFunctionUnsafe->Function
| #bigint => value->toBigIntUnsafe->BigInt
| #symbol => value->toSymbolUnsafe->Symbol
| #object =>
switch isNull(value) {
| true => Null
| false => value->toObjectUnsafe->Object
}
}
}

let toObject = i =>
switch i->classify {
| Object(i) => Some(i)
| _ => None
}

let toBool = i =>
switch i->classify {
| Bool(b) => Some(b)
| _ => None
}

let toFloat = i =>
switch i->classify {
| Number(i) => Some(i)
| _ => None
}

let toBigInt = i =>
switch i->classify {
| BigInt(i) => Some(i)
| _ => None
}

let toString = i =>
switch i->classify {
| String(i) => Some(i)
| _ => None
}

let toSymbol = i =>
switch i->classify {
| Symbol(i) => Some(i)
| _ => None
}

let toFunction = i =>
switch i->classify {
| Function(i) => Some(i)
| _ => None
}

// throws on null or undefined
@get_index external getUnsafe: ('a, string) => option<unknown> = ""
@get_index external getBySymbolUnsafe: ('a, Core__Symbol.t) => option<unknown> = ""

let get = (item, name) => isNullOrUndefined(item) ? None : item->getUnsafe(name)
let getBySymbol = (item, sym) => isNullOrUndefined(item) ? None : item->getBySymbolUnsafe(sym)
Loading