What is the diff between `Date` vs `new Date()`
Source: Dev.to
Introduction
Yesterday I did a deep dive into constructor signatures. Today we’ll look at the difference between using the new keyword (constructor signature) and calling a function directly (call signature), especially with built‑in objects like Date.
If you haven’t read about call constructors yet, check out this article:
Build a simple mini‑dayjs clone logger middleware by call signatures in TypeScript
Constructor vs. Call Signatures
In JavaScript you may encounter code such as:
Boolean();
new Date();
new Array();
new Promise(() => {});
The difference is:
| Signature | How it’s used | What it returns |
|---|---|---|
Constructor (requires new) | new Date(); | An object (instance) |
| Call (function invocation) | Date(); or dayjs(); | A primitive value (or whatever the function returns) |
Why new returns an object
new creates an instance, and an instance must be an object so it can have properties, methods, and a prototype chain. Primitives cannot hold these features, so the language design forces new to return an object.
console.log(typeof String); // function
console.log(typeof String.prototype); // object
console.log(typeof new String()); // object
Prototype Inheritance Overview
JavaScript provides three ways to implement prototype inheritance:
- Object literals
- Constructor functions
- Classes
Example with a class
class Human {}
console.log(typeof new Human()); // object
Example with constructor functions
function Animal() {}
Animal.prototype.eat = function () {
console.log("Nhoammmm");
};
function inheritPrototype(proto) {
function ChainLink() {}
ChainLink.prototype = proto;
return new ChainLink();
}
function Human() {}
Human.prototype = inheritPrototype(Animal.prototype);
Human.prototype.work = function () {
console.log("Coding and earning money!");
};
const kelvynThai = new Human();
console.log(kelvynThai instanceof Human); // true
console.log(typeof kelvynThai); // object
kelvynThai.work(); // Coding and earning money!
kelvynThai.eat(); // Nhoammmm
TypeScript: Typing Constructors and Call Signatures
You can describe a type that works both as a constructor (with new) and as a regular function (call signature).
type MyDate = {
// Constructor signature – returns a String object
new (dateStr: string): String;
// Call signature – returns a primitive string
(dateNum?: number): string;
};
const MyDate: MyDate = function (this: unknown, d?: string | number) {
if (new.target) {
// When called with `new`, return a String object
return new String(`PARSED_DATE:${d}`);
}
// When called as a function, return a primitive string
return d !== undefined ? `TIMESTAMP:${d}` : "DEFAULT_DATE";
} as MyDate;
// Using the constructor
const dateWithNew = new MyDate("Sat 7 Feb 2026");
console.log(dateWithNew, typeof dateWithNew);
// [String: 'PARSED_DATE:Sat 7 Feb 2026'] object
// Using the call signature
const dateWithoutNew = MyDate(123456);
console.log(dateWithoutNew, typeof dateWithoutNew);
// TIMESTAMP:123456 string
// Built‑in example
console.log(new Date(), typeof new Date());
// 2026-02-07T13:58:57.212Z object
Mental model
new→ creates an object (instance)- Direct call → returns a primitive (or whatever the function returns)
Understanding this model makes TypeScript constructor typings much easier to reason about.
When This Knowledge Helps
- Reading built‑in APIs – know whether a function expects
newor not. - Designing flexible libraries – expose both constructor and call signatures when appropriate.
- Modeling function behavior in TypeScript – write accurate type definitions.
- Grasping JavaScript internals – see how objects, prototypes, and instances are created.
Hope this clarifies the differences. Happy coding! 🚀