Variables, Equality & Control
Properties
Truy cập property: dùng dot notation khi có thể
type Luke = { jedi: boolean; age: number };
const luke: Luke = { jedi: true, age: 28 };
// ❌ Tránh: bracket không cần thiết khi key cố định
const isJedi = luke["jedi"];
// ✅ Tốt
const isJedi = luke.jedi;
Truy cập bằng biến: dùng bracket notation []
type Luke = { jedi: boolean; age: number };
const luke: Luke = { jedi: true, age: 28 };
// ❌ Tránh: dot notation không dùng được với biến
function getPropBad(prop: string): boolean | number {
return (luke as Record<string, boolean | number>).prop; // luôn undefined
}
// ✅ Tốt
function getProp(prop: keyof Luke): boolean | number {
return luke[prop];
}
const isJedi = getProp("jedi");
Lũy thừa: dùng toán tử **
// ❌ Tránh
const binary = Math.pow(2, 10);
// ✅ Tốt
const binary = 2 ** 10;
Variables
Luôn khai báo bằng const hoặc let; tránh biến toàn cục
// ❌ Tránh: thiếu const/let → biến global
superPower = new SuperPower();
// ✅ Tốt
const superPower = new SuperPower();
Mỗi biến một khai báo (một const/let)
// ❌ Tránh: nhiều biến một dòng, dễ nhầm
const items = getItems(),
goSportsTeam = true,
dragonball = "z";
// ✅ Tốt
const items = getItems();
const goSportsTeam = true;
const dragonball = "z";
Nhóm const trước, rồi nhóm let
// ❌ Tránh: const và let lẫn lộn
let i: number;
const items = getItems();
let dragonball: string;
const goSportsTeam = true;
let len: number;
// ✅ Tốt
const goSportsTeam = true;
const items = getItems();
let dragonball: string;
let i: number;
let length: number;
Tránh chain assignment (tạo biến global ngầm)
// ❌ Tránh: chỉ a là let, b và c thành global (trong strict mode sẽ lỗi)
(function example(): void {
let a = (b = c = 1) as number;
})();
// console.log(a); // ReferenceError
// console.log(b); // 1 — global
// console.log(c); // 1 — global
// ✅ Tốt
(function example(): void {
let a = 1;
let b = a;
let c = a;
})();
Tránh ++/--; dùng += 1/-= 1
const array = [1, 2, 3];
let num = 1;
// ❌ Tránh
num++;
--num;
for (let i = 0; i < array.length; i++) {
const value = array[i];
if (value) truthyCount++;
}
// ✅ Tốt
num += 1;
num -= 1;
const sum = array.reduce((a, b) => a + b, 0);
const truthyCount = array.filter(Boolean).length;
Không có dòng trống trước/sau = trong assignment
// ❌ Tránh
const foo =
superLongLongLongLongLongLongLongLongFunctionName();
// ❌ Tránh
const foo
= 'một chuỗi rất rất rất rất rất rất rất rất rất rất là dài';
// ✅ Tốt
const foo = (
superLongLongLongLongLongLongLongLongFunctionName()
);
// ✅ Tốt
const foo = 'một chuỗi rất rất rất rất rất rất rất rất rất rất là dài';
Không để biến unused
// ❌ Tránh
const someUnusedVar = 42;
function getX(x: number, y: number): number {
return x; // y unused
}
// ✅ Tốt
function getXPlusY(x: number, y: number): number {
return x + y;
}
const x = 1;
const y = 2;
getXPlusY(x, y);
Hoisting
var bị hoist lên đầu function; const/let nằm trong TDZ (Temporal Dead Zone) cho đến dòng khai báo. Function declaration hoist cả tên và body; function expression chỉ hoist biến.
// var: declaration hoist, assignment không
function exampleVar(): void {
console.log(declaredButNotAssigned); // undefined
var declaredButNotAssigned = true;
}
// const/let: TDZ — truy cập trước dòng khai báo → ReferenceError
function exampleLet(): void {
console.log(declaredButNotAssigned); // ReferenceError
const declaredButNotAssigned = true;
}
// ✅ Tốt: khai báo trước khi dùng
const a = 10;
function fun(): void {}
fun();
class A {}
new A();
Comparison Operators & Equality
Dùng === và !==, không dùng ==/!=
// ❌ Tránh: == ép kiểu, dễ gây bug
if (value == null) {
}
if (count == "3") {
}
// ✅ Tốt
if (value === null || value === undefined) {
}
if (count === 3) {
}
Boolean: có thể dùng shortcut; string/number nên so sánh rõ ràng
// ✅ Tốt: boolean
if (isValid) {
}
// ❌ Tránh: string/number dùng truthy dễ nhầm (0, '')
if (name) {
}
if (collection.length) {
}
// ✅ Tốt
if (name !== "") {
}
if (collection.length > 0) {
}
Trong switch, case/default có khai báo lexical thì bọc trong block {}
// ❌ Tránh: let/const trong case không có block → lỗi redeclare
switch (foo) {
case 1:
let x = 1;
break;
case 2:
const y = 2;
break;
}
// ✅ Tốt
switch (foo) {
case 1: {
let x = 1;
break;
}
case 2: {
const y = 2;
break;
}
default: {
const z = 3;
}
}
Tránh ternary lồng nhau; ưu tiên một dòng hoặc tách biến
// ❌ Tránh
const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null;
// ✅ Tốt: tách biến
const maybeNull = value1 > value2 ? "baz" : null;
const foo = maybe1 > maybe2 ? "bar" : maybeNull;
Tránh ternary thừa: a ? a : b → a || b hoặc a ?? b
// ❌ Tránh
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
const quux = a != null ? a : b;
// ✅ Tốt
const foo = a || b;
const bar = !!c;
const baz = !c;
const quux = a ?? b;
Trộn toán tử: thêm ngoặc để rõ ý (trừ +, -, **)
// ❌ Tránh: thứ tự ưu tiên khó đọc
const foo = (a && b < 0) || c > 0 || d + 1 === 0;
if (a || (b && c)) return d;
// ✅ Tốt
const foo = (a && b < 0) || c > 0 || d + 1 === 0;
if (a || (b && c)) return d;
Nullish coalescing ??: chỉ fallback khi null/undefined
// ❌ Tránh: 0 và '' cũng bị thay bằng default
const value = 0 ?? "default"; // 0 (OK) nhưng ý không rõ
const name = "" ?? "default"; // '' (OK)
// ✅ Tốt: ?? chỉ với null/undefined
const value = null ?? "default";
const user = { name: "John", age: null };
const age = user.age ?? 18;
Blocks
Block nhiều dòng: luôn dùng ngoặc {}
// ❌ Tránh
if (test) return false;
// ✅ Tốt: nhiều dòng thì có block
if (test) {
thing1();
return false;
}
else đặt cùng dòng với } của if
// ❌ Tránh
if (test) {
thing1();
}
else {
thing3();
}
// ✅ Tốt
if (test) {
thing1();
} else {
thing3();
}
Nếu if đã return thì không cần else; có thể tách thành nhiều if
// ❌ Tránh
function foo(x: number, y: number): number {
if (x) {
return x;
} else {
return y;
}
}
// ✅ Tốt
function foo(x: number, y: number): number {
if (x) {
return x;
}
return y;
}
// ✅ Tốt: nhiều nhánh
function cats(x: number, y: number): number | undefined {
if (x) return x;
if (y) return y;
}
Control Statements
Điều kiện dài: xuống dòng, toán tử logic ở đầu dòng
// ❌ Tránh: một dòng quá dài
if ((foo === 123 || bar === "abc") && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
thing1();
}
// ✅ Tốt
if (
(foo === 123 || bar === "abc") &&
doesItLookGoodWhenItBecomesThatLong() &&
isThisReallyHappening()
) {
thing1();
}
Không dùng selection operator thay cho control statement
// ❌ Tránh: dùng && như if
!isRunning && startRunning();
// ✅ Tốt
if (!isRunning) {
startRunning();
}