Nhảy tới nội dung

Optional parameter (tham số tùy chọn)

Optional parameter là tính năng riêng của TypeScript cho phép bỏ qua argument khi truyền vào. Optional parameter được biểu diễn bằng cách viết dấu hỏi ? sau tên argument.

Cú pháp optional parameter

ts
function functionName(argName?: Type) {}
// ^Dấu hiệu optional parameter
ts
function functionName(argName?: Type) {}
// ^Dấu hiệu optional parameter

Optional parameter có thể bỏ qua argument khi gọi function.

ts
function hello(person?: string) {}
hello(); // Có thể gọi mà bỏ qua argument
hello("alice"); // Gọi không bỏ qua cũng OK
ts
function hello(person?: string) {}
hello(); // Có thể gọi mà bỏ qua argument
hello("alice"); // Gọi không bỏ qua cũng OK

Khi bỏ qua sẽ thành undefined

Type của optional parameter là union type của type và undefined. Union type nghĩa là "một trong các type". Trong ví dụ trên, argument person có type là string | undefined.

ts
function hello(person?: string) {}
(parameter) person: string | undefined
ts
function hello(person?: string) {}
(parameter) person: string | undefined

Khi bỏ qua argument, giá trị runtime của optional parameter sẽ là undefined.

ts
function hello(person?: string) {
console.log(person);
}
hello();
undefined
ts
function hello(person?: string) {
console.log(person);
}
hello();
undefined

Xử lý optional parameter

Optional parameter có type là union type với undefined, nên không thể sử dụng trực tiếp. Ví dụ, code sau gọi method toUpperCase của string. Code này sẽ gây compile error. Bởi vì person có thể là type undefined. Và undefined không có method toUpperCase.

ts
function hello(person?: string) {
return "Hello " + person.toUpperCase();
'person' is possibly 'undefined'.18048'person' is possibly 'undefined'.
}
ts
function hello(person?: string) {
return "Hello " + person.toUpperCase();
'person' is possibly 'undefined'.18048'person' is possibly 'undefined'.
}

Để giải quyết vấn đề này, có 2 cách sau.

Gán giá trị default

Viết phân nhánh trường hợp argument là undefined bằng câu lệnh if, và gán giá trị default tại đó.

ts
function hello(person?: string) {
if (typeof person === "undefined") {
person = "anonymous";
}
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
if (typeof person === "undefined") {
person = "anonymous";
}
return "Hello " + person.toUpperCase();
}

Cũng có thể gán giá trị default bằng nullish coalescing assignment operator ??=.

ts
function hello(person?: string) {
person ??= "anonymous";
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
person ??= "anonymous";
return "Hello " + person.toUpperCase();
}

Ngoài ra, cũng có thể làm tương tự bằng cách chỉ định default parameter. Trong hầu hết các trường hợp, nên sử dụng default parameter.

ts
function hello(person: string = "anonymous") {
// ^^^^^^^^^^^^^default parameter
return "Hello " + person.toUpperCase();
}
ts
function hello(person: string = "anonymous") {
// ^^^^^^^^^^^^^default parameter
return "Hello " + person.toUpperCase();
}

📄️ Default parameter

Default parameter cho phép chỉ định giá trị thay thế khi giá trị của tham số là undefined.

Tách xử lý

Một cách khác để xử lý optional parameter là tách xử lý.

ts
function hello(person?: string) {
if (typeof person === "undefined") {
return "Hello ANONYMOUS";
}
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
if (typeof person === "undefined") {
return "Hello ANONYMOUS";
}
return "Hello " + person.toUpperCase();
}

Sự khác biệt với T | undefined

Optional parameter được hiểu là union type T | undefined. Nếu vậy, viết type của argument là T | undefined thì cũng giống nhau. Tại sao TypeScript lại chuẩn bị cách viết khác là dấu hỏi ?? Có sự khác biệt không?

Điều này tạo ra sự khác biệt về việc có thể bỏ qua argument hay không từ phía gọi. Optional parameter có thể bỏ qua chính argument, nhưng argument có type T | undefined không thể bỏ qua.

Ví dụ, function với optional parameter sau có thể gọi mà không có argument.

ts
function hello(person?: string) {}
hello(); // Có thể gọi mà bỏ qua argument
ts
function hello(person?: string) {}
hello(); // Có thể gọi mà bỏ qua argument

Mặt khác, argument có union type với undefined như sau sẽ gây compile error nếu không có argument.

ts
function hello(person: string | undefined) {}
hello();
Expected 1 arguments, but got 0.2554Expected 1 arguments, but got 0.
ts
function hello(person: string | undefined) {}
hello();
Expected 1 arguments, but got 0.2554Expected 1 arguments, but got 0.

Để gọi function này, cần truyền undefined.

ts
function hello(person: string | undefined) {}
hello(undefined);
ts
function hello(person: string | undefined) {}
hello(undefined);

Không thể viết argument thường sau optional parameter

Optional parameter bắt buộc phải viết cuối cùng. Nếu viết argument thường sau optional parameter như sau, sẽ xảy ra compile error.

ts
function func(foo?: string, bar: string) {}
A required parameter cannot follow an optional parameter.1016A required parameter cannot follow an optional parameter.
ts
function func(foo?: string, bar: string) {}
A required parameter cannot follow an optional parameter.1016A required parameter cannot follow an optional parameter.