Skip to content

JS derangement

JavaScript / TypeScript Cheat Sheet — Things C# Doesn't Have


1. Spread operator ...

Expands an array or object into individual elements.

Arrays:

const a = [1, 2, 3];
const b = [4, 5, 6];

const combined = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
const copy = [...a];           // [1, 2, 3] — new array, not a reference

Objects:

const user = { name: 'Abhishek', age: 30 };
const updated = { ...user, age: 31 }; // { name: 'Abhishek', age: 31 }
// later keys overwrite earlier ones

In function calls:

const nums = [1, 2, 3];
Math.max(...nums); // same as Math.max(1, 2, 3)

C# equivalent: roughly params + AddRange + new List(existing) — no single equivalent.


2. Rest operator ...

Opposite of spread. Collects remaining elements into an array. Same syntax, different context.

In functions:

function sum(...numbers: number[]) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

sum(1, 2, 3, 4); // 10

C# equivalent: params int[] numbers

In destructuring:

const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first = 1, second = 2, rest = [3, 4, 5]

3. Destructuring

Pull values out of arrays or objects directly into variables.

Object destructuring:

const user = { name: 'Abhishek', age: 30, city: 'Kolkata' };

const { name, age } = user;
// name = 'Abhishek', age = 30

// rename while destructuring
const { name: userName } = user;
// userName = 'Abhishek'

// default value if property missing
const { name, country = 'India' } = user;
// country = 'India'

Array destructuring:

const [first, second] = [10, 20, 30];
// first = 10, second = 20

// skip elements
const [,, third] = [10, 20, 30];
// third = 30

In function parameters:

function greet({ name, age }: { name: string, age: number }) {
  console.log(`${name} is ${age}`);
}

greet({ name: 'Abhishek', age: 30 });

forkJoin uses this:

forkJoin([getProfile(), getSettings()]).subscribe(([profile, settings]) => {
  // array destructuring on the result
});

No C# equivalent. Closest is tuple deconstruction in C# 7+: var (x, y) = point;


4. Optional chaining ?.

Access nested properties without null checks. Returns undefined if anything in the chain is null/undefined instead of throwing.

const user = { address: { city: 'Kolkata' } };

// Without optional chaining
const city = user && user.address && user.address.city;

// With optional chaining
const city = user?.address?.city; // 'Kolkata'

// If address is null
const user2 = { address: null };
const city2 = user2?.address?.city; // undefined — no error thrown

On methods:

user?.getAddress?.(); // only calls if user and getAddress both exist

On arrays:

arr?.[0]; // safe index access

C# equivalent: ?. — same syntax, C# 6+. You already know this.


5. Nullish coalescing ??

Return right side only if left side is null or undefined. Not for falsy values.

const name = null ?? 'Anonymous';    // 'Anonymous'
const name2 = '' ?? 'Anonymous';     // '' — empty string is NOT null/undefined
const name3 = 0 ?? 42;              // 0 — zero is NOT null/undefined

vs OR operator ||:

const name = '' || 'Anonymous';  // 'Anonymous' — treats empty string as falsy
const name2 = 0 || 42;           // 42 — treats 0 as falsy

?? — only catches null/undefined. Safe for 0 and empty string. || — catches all falsy values. Dangerous for numbers and strings.

C# equivalent: ?? — same behaviour, same syntax.


6. Nullish coalescing assignment ??=

Assign only if current value is null or undefined.

let user = null;
user ??= 'Anonymous'; // user = 'Anonymous'

let name = 'Abhishek';
name ??= 'Anonymous'; // name stays 'Abhishek'

7. Array methods — JS vs C# mapping

const nums = [1, 2, 3, 4, 5];

// map → Select
nums.map(x => x * 2);              // [2, 4, 6, 8, 10]

// filter → Where
nums.filter(x => x > 2);           // [3, 4, 5]

// reduce → Aggregate
nums.reduce((acc, x) => acc + x, 0); // 15

// find → FirstOrDefault
nums.find(x => x > 3);             // 4

// findIndex → no direct equivalent
nums.findIndex(x => x > 3);        // 3 (index)

// some → Any
nums.some(x => x > 4);             // true

// every → All
nums.every(x => x > 0);            // true

// includes → Contains
nums.includes(3);                   // true

// flat — flatten nested arrays
[[1, 2], [3, 4]].flat();           // [1, 2, 3, 4]

// flatMap — map then flat in one step
[[1, 2], [3, 4]].flatMap(x => x);  // [1, 2, 3, 4]

8. Object methods

const user = { name: 'Abhishek', age: 30 };

Object.keys(user);    // ['name', 'age']
Object.values(user);  // ['Abhishek', 30]
Object.entries(user); // [['name', 'Abhishek'], ['age', 30]]

// entries is useful for iteration
Object.entries(user).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

// Object.assign — merge objects (spread is cleaner)
const merged = Object.assign({}, user, { city: 'Kolkata' });

// structuredClone — deep clone
const clone = structuredClone(user);

9. Template literals

const name = 'Abhishek';
const age = 30;

// Old way
const msg = 'Hello ' + name + ', you are ' + age;

// Template literal
const msg = `Hello ${name}, you are ${age}`;

// Multiline
const html = `
  <div>
    <p>${name}</p>
  </div>
`;

// Expression inside
const result = `${2 + 2} is four`;

C# equivalent: $"Hello {name}" — same concept, different delimiter.


10. Short circuit evaluation

JS uses && and || for more than just booleans.

// && — return right side if left is truthy, otherwise return left
const result = user && user.name; // user.name if user exists, otherwise user (null/undefined)

// Common in JSX/templates
isLoggedIn && showDashboard(); // only calls if isLoggedIn is true

// || — return left side if truthy, otherwise right side
const name = inputName || 'Anonymous'; // 'Anonymous' if inputName is falsy

11. Comma operator and ternary

// Ternary — inline if/else
const label = count === 1 ? 'item' : 'items';

// Nested ternary — avoid, hard to read
const label = count === 0 ? 'empty' : count === 1 ? 'one item' : 'many items';

C# equivalent: condition ? a : b — same syntax.


12. typeof and instanceof

typeof 'hello';     // 'string'
typeof 42;          // 'number'
typeof true;        // 'boolean'
typeof undefined;   // 'undefined'
typeof null;        // 'object' ← famous JS bug, not actually an object
typeof {};          // 'object'
typeof [];          // 'object' ← arrays are objects in JS
typeof function(){}; // 'function'

// instanceof — check class/constructor
[] instanceof Array;   // true
user instanceof User;  // true

13. Truthy and falsy — the JS gotcha

These values are falsy in JS — everything else is truthy:

false
0
-0
0n        // BigInt zero
''        // empty string
null
undefined
NaN
// Gotcha — empty array and empty object are TRUTHY
if ([]) console.log('truthy');  // prints — array is truthy even if empty
if ({}) console.log('truthy');  // prints — object is truthy even if empty

// This is why ?? is safer than || for defaults
const count = 0;
count || 'none';   // 'none' — WRONG, 0 is a valid value
count ?? 'none';   // 0 — CORRECT

14. == vs ===

Always use ===. Always.

1 == '1';   // true  — type coercion, compares value after converting
1 === '1';  // false — strict equality, type must match too

null == undefined;  // true  — special case
null === undefined; // false

0 == false;  // true
0 === false; // false

== does type coercion. Unpredictable. === does not. Use === everywhere.