This is apparently a homely strong typing setting:
/** * A recursive descent analyzer which takes a value and a typehint, validating * whether or not the value matches the typehint. * The function will call it self as long as both the value and the typehint * yields a nested component. This means that we will never recurse deeper * than needed, and also that we automatically get support for * > equals([], 'array<string>') // true * > equals(['string'], 'array') // true */ function equals(value, node) { var type = typeof value; var subType; var nextNode; var nextValue; //: Nullable types are delimited with a leading ? //: ?string, ?boolean, etc. var nullable = /^\?/.test(node); if (nullable) { node = node.substring(1); } //: snip ... switch (type) { // start by testing the most common types case 'boolean': case 'number': case 'string': case 'undefined': break; default: //: snip ... // let functions with signatures also match 'function' type = value.__TCmeta && node !== 'function' ? value.__TCmeta.signature : 'function'; } else if (type === 'object' || type === 'function') { // HTMLObjectElements has a typeof function in FF var constructor = value.constructor; if (constructor && constructor.__TCmeta) { // The value is a custom type //: snip ... while (constructor && constructor.__TCmeta) { if (constructor.__TCmeta.type == node) { type = node; break; } constructor = constructor.__TCmeta.superClass; } //: snip ... } } } } if (nullable && /undefined|null/.test(type)) { return true; } if (type in typeInterfaces) { var interfaces = typeInterfaces[type], i = interfaces.length; while (i--) { if (interfaces[i] === node) { type = node; break; } } } currentType.push(type); return nextValue && nextNode ? node === type && equals(nextValue, nextNode) : subType && nextNode ? node === type && subType === nextNode : node === type; }
function matches(value, node) { var nodes = node.split('|'), i = nodes.length; while (i--) { currentType = []; if (equals(value, nodes[i])) { return true; } } return false; }
The reason they use the annotate function is because of type resolution for custom types and function signatures. Without annotate you can only do matches(someVar, "function") . With annotate you can make matches(someVar, "function(string, ?int)|function(string)") and accept only functions that accept a string and a NULL integer value or functions that accept only a string.
Sean vieira
source share