Tìm kiếm trang web

javascript - Tại sao TypeScript yêu cầu các tham số tùy chọn phải nằm sau các tham số bắt buộc?


Cái này hoạt động:

public console(message: string | undefined, suppressLevel: boolean) {}

Nhưng điều này thì không:

public console(message?: string, suppressLevel: boolean) {}

Xem xét rằng ? dường như cơ bản là một cách viết tắt cho | undefined (và khi bạn di chuột trong VS Code nó cũng hiện như vậy), thì tại sao TypeScript lại phân biệt? Bạn có thể truyền rõ ràng undefined cho một tham số tùy chọn và nó sẽ giống như không chỉ định tham số đó ở cuối.

Câu trả lời #1

Quan trọng nhất, đây là một thực tế về JavaScript mà chỉ trở nên rõ ràng hơn khi định kiểu mạnh mẽ cho chữ ký của hàm.

Các tham số của hàm được ràng buộc theo vị trí trong danh sách đối số. Đối số được truyền đầu tiên sẽ được ràng buộc với tham số đầu tiên. Đối số được truyền thứ hai sẽ được ràng buộc với tham số thứ hai. Và cứ như vậy. Với các tham số tùy chọn ở cuối, bộ máy javascript sẽ biết cách ràng buộc các tham số cuối với undefined khi danh sách đối số quá ngắn. Bất kể lời gọi ngắn bao nhiêu, thì số lượng các tham số cuối đó sẽ được đặt là undefined.

Nếu các tham số tùy chọn có thể nằm ở giữa hoặc ở đầu, sẽ không có đủ thông tin tại nơi gọi để biết tham số nào nên được gán cho đối số nào.

function fn(a?: number, b: number) { /* ... */ }

fn(42);

Nếu chữ ký của fn hợp lệ, fn(42) sẽ gây ra sự mơ hồ. b có nên được gán giá trị 42 để lại a undefined? Hay a nên được gán giá trị 42 với b để lại undefined (và do đó sẽ gây ra lỗi kiểu?) Trong tình huống cụ thể này, bạn có thể muốn trình kiểm tra kiểu của TypeScript GIẢ SỬ rằng không có lỗi và thay vào đó cố gắng hết sức để tìm một cách hiểu hợp lệ về lời gọi (cách hiểu mà b nhận giá trị 42) nhưng đó sẽ là một thuật toán giải quyết nạp chồng tốn kém hơn và vẫn sẽ có những trường hợp gây mơ hồ và các quy tắc sẽ quá phức tạp để có ích (ví dụ fn2(a?: number, b: number, c?: number) { /* ... */ } với fn(42, 3.1415))

Javascript, bằng cách có các đối số theo vị trí với các đối số cuối tùy chọn, và với Typescript cho phép chúng ta chú thích rõ ràng các quá tải chữ ký được phép, đạt được sự cân bằng tuyệt vời giữa khả năng biểu đạt, tính hợp lý (hiệu suất của trình kiểm tra kiểu) và tránh lỗi.

Nếu việc giải quyết nạp chồng hàm linh hoạt hơn theo cách đó, thì nó tất yếu phải xem nhiều lần gọi là hợp lệ, điều này thực sự có thể là lỗi. Hoặc nó sẽ đặt gánh nặng lên thân hàm để xử lý tất cả các biến thể một cách đầy đủ, chẳng hạn như biến tất cả các tổ hợp tham số thành các kiểu hợp nhất với nhau và sau đó phải tách chúng ra trong mã, làm cho việc đọc trở nên khó khăn hơn.

Câu trả lời #2

? không phải là cách viết tắt của string | undefined. Nó là một tham số tùy chọn. Nghĩa là - bạn có thể truyền giá trị kiểu mong đợi, hoặc không.

string | undefined, ngược lại, có nghĩa là bạn phải rõ ràng truyền một giá trị mà là một chuỗi hoặc undefined. Giá trị có thể là undefined, nhưng tham số vẫn tồn tại.

Sẽ thật nghịch lý khi truyền một thuộc tính sau một thuộc tính tùy chọn - bạn sẽ không thể thiết lập nó, vì việc thiết lập nó có nghĩa là phải thiết lập một thuộc tính trước đó, điều này có nghĩa là thuộc tính trước nó sẽ không còn là tùy chọn!

Bài viết liên quan