:
/**
* 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;
}
/**
* Given a value and a typehint (can be a union type), this will return
* whether or not the passed in value matches the typehint.
*/
function matches(value, node) {
var nodes = node.split('|'), i = nodes.length;
while (i--) {
currentType = [];
if (equals(value, nodes[i])) {
return true;
}
}
return false;
}
理由彼らannotate
関数を使用すると、カスタム型と関数シグネチャの型ヒントが許可されます。 annotate
がなければ、matches(someVar, "function")
しかできません。 annotate
を使用すると、matches(someVar, "function(string, ?int)|function(string)")
を実行し、文字列を受け取り、NULL可能なinteger
の関数、または文字列のみを受け入れる関数を受け入れることができます。
なぜ下降票と閉票かはわかりませんが、それは興味深い質問であり、SOの範囲内です。なぜFacebookがこれをやっているのか私は非常に不思議です。 –
誰かが私が既に言及されていることを広げたいと思っているなら、私はうれしいです:) –