README
type-precedence
type-precedence
is a library used to determine precedence of types that can be checked with type-check
. So, if a value mathes more types, you can find the most specific one. Used, for example in defn
, to choose the best signature of an overloaded function.
For reference on how a type can be specfied, please see Type Format or Quick Examples for
type-check
$ npm install type-precedence
Type Precedence
__ <= *
- * is the most general type (__
stands for any type){x: __} < Object
- an explicit object is more specific thanObject
[__] < Array
- same as for object{x: __} < {...}
- a subset is more general{x: __, y: __, ...} < {x: __, ...}
- a subset with more keys specified is more specificTypeA < TypeA | TypeB
TypeA < Maybe TypeA
Number | String < String | Number
for value1
String | Number < Number | String
for value's'
- everything* above applied recursively for
[arrays]
,{fields}
or(tuples)
(e.g{x: [Number]} < {x: [*]}
)
*actually almost everything - (String | Number, *)
and (Number | String, *)
would be equal for any value. So ambiguous |
(i.e. where you need a target value to decide which is best) will not work recursively.
Usage
the following examples are written in LiveScript, but, of course, the library can be used for javascript too
{best-type, sort-types, compare-types} = require \type-precedence
best-type in: types[, matching: target]
Gets the most specific type from a list of types, optionally matching a target value
best-type in: <[Array [*] *]> # [*]
best-type in: ['Number | String', 'String | Number'], matching: 1 # 'Number | String', since the value is a Number
sort-types types[, matching: target]
Sorts the types by precedence - the most specific will be first in the sorted list. It optionally checks against a target value
sort-types <[Array [*] *]> # <[[*] Array *]>
sort-types ['{x: Number, ...}' '{...}' '{x: *}' '*' 'Object'] # ['{x: *}' '{x: Number, ...}' '{...}' 'Object' '*']
compare-types type-a, type-b[, matching: target]
Compare two types, optionally checking against a target value. It returns -1, 0, or 1.
compare-types '{x: String, ...}', '{x: *, ...}' # -1
compare-types '(*)', '(Object)' # 1
compare-types '{x: *, ...}', '{y: *, ...}' # 0 - two subsets with same number of specified keys
... matching: target
Providing the optional argument matching: target
to any of the functions above will do the following:
- help choosing the best type when ambiguous
compare-types 'Number | String', 'String | Number' # 0, because there is no clear winner
compare-types 'Number | String', 'String | Number', matching: \string # 1, because 'String | Number' is more specific in this case
- validate the types against the target value, throwing an Error if one of the types doesn't match
compare-types 'Number', 'String' # 0
compare-types 'Number', 'String', matching: 1 # throws '<1> does not match <String>'