Skip to content

Commit

Permalink
narrow: add partial support for typeof narrowing
Browse files Browse the repository at this point in the history
  • Loading branch information
Raynos committed Sep 29, 2016
1 parent d69190d commit f399e2d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
1 change: 1 addition & 0 deletions test/index.js
Expand Up @@ -34,6 +34,7 @@ require('./unit/intersection-types.js');
require('./unit/construct-builtins.js');
require('./unit/prototype-inheritance.js');
require('./unit/multiple-returns.js');
require('./unit/narrow-mixed.js');

require('./batch-client-constructor.js');
require('./batch-client-methods.js');
Expand Down
23 changes: 23 additions & 0 deletions test/unit/narrow-mixed.js
@@ -0,0 +1,23 @@
'use strict';

var JSIGSnippet = require('../lib/jsig-snippet.js');

JSIGSnippet.test('overloading an event emitter object', {
snippet: function m() {/*
function parseJSONNumber(str) {
var x = JSON.parse(str);
if (typeof x === 'number') {
return x;
}
return null;
}
*/},
header: function h() {/*
parseJSONNumber : (String) => Number | null
*/}
}, function t(snippet, assert) {
snippet.compileAndCheck(assert);
assert.end();
});
3 changes: 2 additions & 1 deletion type-checker/builtin-definitions/es5.hjs
Expand Up @@ -69,5 +69,6 @@ Object : {
}

JSON : {
stringify: (%Boolean%%Mixed) => String
stringify: (%Boolean%%Mixed) => String,
parse: (String) => %Boolean%%Mixed
}
52 changes: 51 additions & 1 deletion type-checker/narrow-type.js
Expand Up @@ -5,6 +5,7 @@ var assert = require('assert');
var getUnionWithoutBool = require('./lib/get-union-without-bool.js');
var updateObject = require('./lib/update-object.js');
var isSameType = require('./lib/is-same-type.js');
var JsigAST = require('../ast/');

module.exports = NarrowType;

Expand Down Expand Up @@ -69,8 +70,57 @@ function narrowIdentifier(node, ifBranch, elseBranch) {

NarrowType.prototype.narrowBinaryExpression =
function narrowBinaryExpression(node, ifBranch, elseBranch) {
if (node.left.type === 'UnaryExpression' &&
node.left.operator === 'typeof'
) {
return this.narrowTypeofExpression(node, ifBranch, elseBranch);
}

// TODO: support `x === null`
// TODO: support `typeof y === "{{tag}}"`
};

NarrowType.prototype.narrowTypeofExpression =
function narrowTypeofExpression(node, ifBranch, elseBranch) {
var identifier = node.left.argument;
if (identifier.type !== 'Identifier') {
// TODO: support non trivial expressions
return null;
}

if (node.operator !== '===') {
// TODO: support !==, and others... ?
return null;
}

var type = this.meta.verifyNode(identifier, null);
if (!type) {
return null;
}

if (type.type !== 'typeLiteral' ||
!type.builtin || type.name !== '%Boolean%%Mixed'
) {
// TODO: support narrowing other things then Mixed
return null;
}

var typeTagNode = node.right;
if (node.right.type !== 'Literal') {
// Right hand side of equal operator
return null;
}

var typeTagValue = typeTagNode.value;
if (typeTagValue === 'number') {
if (ifBranch) {
ifBranch.restrictType(
identifier.name, JsigAST.literal('Number')
);
}
} else {
// TODO: support other tags
return null;
}
};

NarrowType.prototype.narrowLiteral =
Expand Down

0 comments on commit f399e2d

Please sign in to comment.