question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

In target: ES5, Base class constructor's primitive return value should be ignored

See original GitHub issue

Bug Report

🔎 Search Terms

class, extends, constructor, return primitive

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about class constructors

⏯ Playground Link

Playground link with relevant code

💻 Code

new class extends class {
  constructor() {
    return 1;
  }
} {
  constructor() {
    super();
    console.log(typeof this);
  }
}

🙁 Actual behavior

Logs “number”

🙂 Expected behavior

Logs “object”

Issue Analytics

  • State:open
  • Created 10 months ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
fatcerberuscommented, Dec 3, 2022

You probably should have specified that this only happens with ES5-downleveled code. From the OP it seemed like you meant this happened regardless of target (which would indicate it was just normal JS behavior).

0reactions
Josh-Cenacommented, Dec 6, 2022

I can guess the historical context here (tsc implementing classes before the latter getting standardized), but IMO the current behavior doesn’t benefit anyone and is unlikely to be relied on. If this is a primitive, it means you can’t mutate it whatsoever. Unless you do something really weird like:

function SomethingThatReturnsEitherObjectOrNumberIDK() {
  if (somethingNotGoingWell) return 1;
  return {
    the: "actual object that I want to construct",
  };
}

declare class SomethingThatReturnsEitherObjectOrNumberIDK {
  the?: string;
}

new class extends SomethingThatReturnsEitherObjectOrNumberIDK {
  constructor() {
    super();
    if (typeof this === "number")
      return { the: `number wrapped into an object: ${this}` }; // type: { the: never }
  }
}

But that doesn’t even get correct types! Why would someone use tsc, choose its bizarre subclassing behavior, but also disregard the types?

Built-in subclassing not working is a missed but understandable tradeoff, but this one seems niche and not as breaking-change-prone, while increasing tsc’s conformance.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Chapter 17. Objects and Inheritance - Exploring JS
The value of a property can be any JavaScript value, including a function. ... 3: Constructors—Factories for Instances), are roughly similar to classes...
Read more >
Constructor, operator "new" - The Modern JavaScript Tutorial
That can be done using constructor functions and the "new" operator. ... If return is called with a primitive, it's ignored.
Read more >
Function.prototype.bind() - JavaScript - MDN Web Docs - Mozilla
The newly bound thisArg value is ignored, because the target function of boundFn2 , which is boundFn , already has a bound this...
Read more >
typescript-cheatsheet - GitHub Pages
The cheatsheet contains references to types, classes, decorators, ... You may commonly see this as the return type of functions that do not...
Read more >
Classes in ECMAScript 6 (final semantics) - 2ality
You use this class just like an ES5 constructor function: ... class MyClass { get prop() { return 'getter'; } set prop(value) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found