Skip to content

console.log ​

console.log prints exactly what Node prints: numbers in JavaScript's shortest round-trip form (0.1 + 0.2 is 0.30000000000000004, -0 prints as -0), strings quoted inside containers, class names before instances, Map(n) {...} and Set(n) {...}, and Node's line breaking once a value gets wide. Format directives (%s, %d, %i, %f, %j, %o, %O, %c, %%) apply when the first argument is a string.

ts
// console.log prints values the way Node's util.inspect does, and honors format directives.
class Point {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

console.log(1 / 3, -0, 1e21, NaN, "text", true, null, undefined);
console.log([1, "two", [3, 4]], { name: "ada", tags: ["x"], nested: { depth: 2 } });
console.log(new Point(1, 2), [new Point(3, 4)]);
const m = new Map<string, number>();
m.set("a", 1);
console.log(m, new Set<number>([1, 2]));
console.log("%s scored %d (%i%%)", "ada", 9.5, 95.4);
console.log(`template ${[1, 2].join("+")} ${-0} ${0.1 + 0.2}`);
text
0.3333333333333333 -0 1e+21 NaN text true null undefined
[ 1, 'two', [ 3, 4 ] ] { name: 'ada', tags: [ 'x' ], nested: { depth: 2 } }
Point { x: 1, y: 2 } [ Point { x: 3, y: 4 } ]
Map(1) { 'a' => 1 } Set(2) { 1, 2 }
ada scored 9.5 (95%)
template 1+2 0 0.30000000000000004

Every object carries its runtime shape, so printing reads the real fields of the real object, even when it is reached through an interface or a union.

Values as text ​

String(x), template literals, + with a string, and join convert values the way Node does: arrays join their elements with commas, a plain object is [object Object], and an instance of a class that declares toString(): string converts by calling it.

ts
// How String(), template literals, + and join turn values into text, the same as Node.
interface Point {
  x: number;
  y: number;
}

class Money {
  cents: number;
  constructor(cents: number) {
    this.cents = cents;
  }
  toString(): string {
    return `$${(this.cents / 100).toString()}`;
  }
}

const p: Point = { x: 1, y: 2 };
const xs = [[1, 2], [3]];
const price = new Money(1250);

console.log(String(p), `${p}`, "p=" + p);
console.log(String(xs), `[${xs}]`, [p, p].join(" | "));
console.log(String(price), `total: ${price}`, "cost " + price);
console.log(`${null} ${undefined} ${true}`);
text
[object Object] [object Object] p=[object Object]
1,2,3 [1,2,3] [object Object] | [object Object]
$12.5 total: $12.5 cost $12.5
null undefined true

Converting a function (Node prints its source text), an object with a valueOf method, or an object whose own toString() its declared type does not declare is rejected (CS1238). So is join on an array of objects that have their own toString().

Limits today ​

  • A value that can hold something the runtime cannot render the way Node does (for example a promise) is rejected in console.log and JSON.stringify (CS1238).
  • console.log is the only console method today; console.error and the others fail to typecheck (CS0001).

Next: Accepted subset, the complete list.