Skip to content

Js constructor function fixes#22721

Merged
sandersn merged 7 commits into
masterfrom
js-constructor-function-fixes
Mar 20, 2018
Merged

Js constructor function fixes#22721
sandersn merged 7 commits into
masterfrom
js-constructor-function-fixes

Conversation

@sandersn
Copy link
Copy Markdown
Member

JS constructors had a couple of bugs with strictNullChecks (which people actually do use with checkJs, see the recent post by @OliverJAsh).

  1. this-assignments in a function added undefined to the type of all properties:
function A() {
  this.x = 1
}

Incorrectly had x: number | undefined not x: number.

  1. Callable constructors, which have a check to see whether they were called instead of newed, incorrectly unioned undefined to the instance type. This was unneeded and annoying:
function A() {
  if (!(this instanceof A)) {
    return new A()
  }
  this.x = 1
}
var a = new A()

This incorrectly had a: { x: number } | undefined when it should have been a: { x: number }

Fixes #22414
Fixes #22641

Note that the second fix checks two things to distinguish a constructor function from a normal one:

  1. Whether the function is a javascript constructor
  2. Whether the function returns a type with the symbol of the constructor function itself -- that is, whether it has a statement return new A() somewhere inside function A. It doesn't check whether this statement is inside a conditional.

@sandersn sandersn requested review from a user and weswigham March 20, 2018 17:28
Comment thread src/compiler/checker.ts

if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) {
if (getThisContainer(expression, /*includeArrowFunctions*/ false).kind === SyntaxKind.Constructor) {
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An explanatory comment would be nice to have here

@sandersn sandersn merged commit 1074819 into master Mar 20, 2018
@sandersn sandersn deleted the js-constructor-function-fixes branch March 20, 2018 18:24
Comment thread src/compiler/checker.ts
if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) {
if (getThisContainer(expression, /*includeArrowFunctions*/ false).kind === SyntaxKind.Constructor) {
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
const isPrototypeProperty = isBinaryExpression(thisContainer.parent) &&
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only used if thisContainer.kind === SyntaxKind.FunctionExpression, might want to avoid computing this otherwise.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

3 participants