Đây là kết quả hàng đầu trên Google đối với tôi vì vậy tôi nghĩ tôi nên cung cấp các giải pháp mà tôi tìm thấy.
Sử dụng bigint
Bây giờ là năm 2020 và bigintđã được chấp nhận, nó xứng đáng được đề cập đến. Bạn có thể làm đơn giản như dưới đây. Lưu ý rằng bigints đi kèm với tác động hiệu suất lớn hơn so với a number.
const myNumber: bigint = 10n
Sử dụng loại danh nghĩa / loại được gắn thẻ / loại mờ
Một giải pháp thay thế là sử dụng một loại danh nghĩa, nhưng nó được cho là kém tiện dụng hơn và tôi không chắc liệu nó có nhanh hơn hay không bigint, nhưng mô hình chung chung cho bất kỳ loại nào, không chỉ number. TypeScript không có hỗ trợ "hạng nhất" cho việc này, vì vậy bạn phải thực hiện một vụ hack táo tợn. Có một thư viện cho điều này được gọi là newtype-tsbao gồm các loại phổ biến như Integervậy, vì vậy bạn có thể chỉ muốn sử dụng nó, nhưng tôi sẽ giải thích hoạt động bên dưới.
Để bắt đầu, chúng tôi xác định integerloại.
const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }
Các TAG đảm bảo rằng chúng ta có một giá trị duy nhất để chúng ta không vô tình tạo ra một đối tượng có cùng một khóa và chúng ta cũng đặt trường trở thành một biểu tượng duy nhất vì cùng một lý do. Bây giờ, số nguyên của bạn sẽ không thực sự có trường đối tượng này nhưng điều đó tốt.
Với điều này, bạn vẫn có thể thêm integervào numberviệc sử dụng +. Không tốt. Vì vậy, bạn có thể thực thi an toàn kiểu đối với các đối số ở đây bằng cách kết hợp hệ thống kiểu với một hàm. Tôi chỉ sẽ gọi nó là bảo vệ, và một lần nữa như bạn có thể thấy nó không dành riêng cho integers - bạn có thể tạo ra các loại mờ hơn và sử dụng lại.
type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)
Nếu bạn cố gắng gọi điều đó bằng number
const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)
bạn sẽ gặp lỗi như bên dưới
Argument of type '10' is not assignable to parameter of type 'integer'.
Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)
Lưu ý rằng bạn không thực thi kiểu trả về ở đây (vì bạn phải sử dụng as integer) và một số toán tử như /sẽ trả về số dấu phẩy động, vì vậy bạn có thể vẫn muốn thực hiện kiểm tra thời gian chạy hoặc thêm một Math.roundvào phiên bản chuyên biệt của guard, nhưng điều này ít nhất sẽ đảm bảo bạn không cố gắng sử dụng hai loại số riêng biệt với nhau - tưởng tượng bạn có GBPvà USDvà cố gắng thêm những người, mà có thể sẽ không được những gì bạn dự định.