Strings & Functions
Strings
Dùng double quotes "" cho string
// ❌ Tránh
const name = 'Capt. Janeway';
// ✅ Tốt
const name = "Capt. Janeway";
Chuỗi dài: dùng template string, tránh nối nhiều dòng bằng +
// ❌ Tránh
const errorMessage =
"This is a " +
"super long error that was thrown because of Batman. " +
"When you stop to think about it, you would get nowhere fast.";
// ✅ Tốt
const errorMessage = `This is a super long error that was thrown because of Batman.
When you stop to think about it, you would get nowhere fast.`;
Tạo chuỗi động: dùng template string thay vì nối
// ❌ Tránh
function sayHi(name: string): string {
return "How are you, " + name + "?";
}
// ✅ Tốt
function sayHi(name: string): string {
return `How are you, ${name}?`;
}
Không dùng eval() trên chuỗi — dễ lỗ hổng bảo mật
// ❌ Tránh: không bao giờ dùng
const code = "alert('xss')";
eval(code);
// ✅ Tốt: dùng JSON.parse cho JSON, hoặc logic an toàn khác
const data = JSON.parse(jsonString) as MyType;
Functions
Ưu tiên named function expression thay vì function declaration
Function declaration bị hoisting, dễ tham chiếu trước khi định nghĩa, khó đọc. Nên đặt tên cho function expression.
// ❌ Tránh
function foo(): void {}
// ✅ Tốt
const short = function longUniqueMoreDescriptiveLexicalFoo(): void {};
IIFE: bọc trong ngoặc tròn
// ❌ Tránh: không bọc, có thể bị ASI nhầm
function () {
console.log("Welcome.");
}();
// ✅ Tốt
(function (): void {
console.log("Welcome.");
})();
Không khai báo function trong block không phải function (if, while, …)
Gán function vào biến rồi gán trong block.
// ❌ Tránh: hành vi khác nhau giữa các runtime
if (currentUser) {
function test(): void {
console.log("Yup.");
}
}
// ✅ Tốt
let test: (() => void) | undefined;
if (currentUser) {
test = (): void => {
console.log("Yup.");
};
}
Không đặt tên tham số là arguments
Sẽ che arguments của function.
// ❌ Tránh: arguments bên trong là tham số, không phải object arguments
function foo(name: string, options: object, arguments: unknown): void {
console.log(arguments); // là tham số thứ 3, không phải danh sách đối số
}
// ✅ Tốt
function foo(name: string, options: object, args: unknown): void {
console.log(args);
}
Dùng rest ... thay vì arguments
// ❌ Tránh: arguments là array-like, không có .map/.filter
function concatenateAll(): string {
const args = Array.prototype.slice.call(arguments);
return args.join("");
}
// ✅ Tốt
function concatenateAll(...args: string[]): string {
return args.join("");
}
Dùng default parameter thay vì mutate tham số
type RequestOptions = { timeout?: number };
// ❌ Tránh: mutate tham số
function handleThings(opts: RequestOptions): void {
if (!opts) opts = {};
opts.timeout = opts.timeout ?? 1000;
}
// ✅ Tốt
function handleThings(opts: RequestOptions = {}): void {
const timeout = opts.timeout ?? 1000;
}
Default parameter đặt cuối; không side effect trong default
// ❌ Tránh: default ở giữa, tham số sau khó truyền
function handleThings(opts: RequestOptions = {}, name: string): void {}
// ✅ Tốt
function handleThings(name: string, opts: RequestOptions = {}): void {}
// ❌ Tránh: side effect trong default
let b = 1;
function count(a: number = b++): void {
console.log(a);
}
count(); // 1
count(); // 2 — khó đoán
// ✅ Tốt
function count(a: number = 0): void {
console.log(a);
}
Không mutate hoặc reassign tham số
// ❌ Tránh
function f1(obj: { key: number }): void {
obj.key = 1;
}
function f2(a: number): void {
a = 1;
}
// ✅ Tốt
function f1(obj: { key: number }): void {
const newKey = obj.key !== undefined ? obj.key : 1;
// tạo object mới hoặc return thay vì mutate obj
}
function f2(a: number): number {
const b = a || 1;
return b;
}
Gọi hàm variadic: dùng spread ...
const x = [1, 2, 3, 4, 5];
// ❌ Tránh
console.log.apply(console, x);
// ✅ Tốt
console.log(...x);
// ✅ Tốt: với new
const date = new Date(...[2024, 2, 15]);
Arrow Functions
Callback vô danh: dùng arrow function
// ❌ Tránh
[1, 2, 3].map(function (x: number) {
const y = x + 1;
return x * y;
});
// ✅ Tốt
[1, 2, 3].map((x: number) => {
const y = x + 1;
return x * y;
});
Body chỉ một biểu thức không side effect: bỏ ngoặc và dùng implicit return
// ❌ Tránh: không return, trả về undefined
[1, 2, 3].map((number: number) => {
`A string containing the ${number}.`;
});
// ✅ Tốt
[1, 2, 3].map((number: number) => `A string containing the ${number}.`);
// ✅ Tốt: nhiều dòng thì bọc ngoặc
[1, 2, 3].map((number: number) => ({
value: number,
label: `Item ${number}`,
}));
Luôn dùng ngoặc quanh tham số
// ❌ Tránh: thêm/xóa tham số dễ gây diff rối
[1, 2, 3].map((x) => x * x);
// ✅ Tốt
[1, 2, 3].map((x) => x * x);
// ✅ Tốt: một tham số cũng nên có ngoặc
[1, 2, 3].map((number) => number + 1);
Tránh nhầm => với <= / >=
type Item = { height: number; largeSize: number; smallSize: number };
// ❌ Tránh: dễ đọc nhầm
const itemHeight = (item: Item) =>
item.height <= 256 ? item.largeSize : item.smallSize;
// ✅ Tốt: bọc biểu thức return trong ngoặc
const itemHeight = (item: Item): number =>
item.height <= 256 ? item.largeSize : item.smallSize;
// ✅ Tốt: dùng block rõ ràng
const itemHeight = (item: Item): number => {
const { height, largeSize, smallSize } = item;
return height <= 256 ? largeSize : smallSize;
};