Default type parameter
Giống như chỉ định giá trị mặc định cho tham số của hàm, trong generics cũng có thể chỉ định default type parameter.
Ví dụ, hãy định nghĩa một kiểu MyErrorEvent biểu diễn error event. Kiểu này lưu trữ một error object bất kỳ và loại của nó dưới dạng string.
tstypeMyErrorEvent <T > = {error :T ;type : string;};
tstypeMyErrorEvent <T > = {error :T ;type : string;};
Kiểu này có thể được sử dụng như sau.
tsclassNetworkError extendsError {constructor(e ?: string) {super(e );this.name = new.target .name ;}}consterrorEvent :MyErrorEvent <Error > = {error : newError ("エラーです"),type : "syntax",};constnetworkErrorEvent :MyErrorEvent <NetworkError > = {error : newNetworkError ("ネットワークエラーです"),type : "network",};
tsclassNetworkError extendsError {constructor(e ?: string) {super(e );this.name = new.target .name ;}}consterrorEvent :MyErrorEvent <Error > = {error : newError ("エラーです"),type : "syntax",};constnetworkErrorEvent :MyErrorEvent <NetworkError > = {error : newNetworkError ("ネットワークエラーです"),type : "network",};
Khi viết xử lý exception, thường không chuẩn bị đầy đủ các error class tương ứng như NetworkError, mà xử lý bằng Error chuẩn trong nhiều trường hợp. Tuy nhiên, ở trạng thái hiện tại, phải luôn chỉ định kiểu T của generics trong MyErrorEvent, điều này rất phiền phức.
ts// Kiểu T là bắt buộc nên phải chỉ định MyErrorEvent<Error>.constGeneric type 'MyErrorEvent' requires 1 type argument(s).2314Generic type 'MyErrorEvent' requires 1 type argument(s).errorEvent := { MyErrorEvent error : newError ("エラーです"),type : "syntax",};
ts// Kiểu T là bắt buộc nên phải chỉ định MyErrorEvent<Error>.constGeneric type 'MyErrorEvent' requires 1 type argument(s).2314Generic type 'MyErrorEvent' requires 1 type argument(s).errorEvent := { MyErrorEvent error : newError ("エラーです"),type : "syntax",};
Do đó, bằng cách viết <T = Error>, ta chỉ định Error làm default type parameter.
tstypeMyErrorEvent <T =Error > = {error :T ;type : string;};
tstypeMyErrorEvent <T =Error > = {error :T ;type : string;};
Bằng cách chỉ định Error làm default type parameter, kiểu T của generics chỉ cần chỉ định khi cần thiết, và nếu không chỉ định gì thì tự động trở thành Error.
ts// Nhờ chỉ định default type parameter, có thể bỏ qua chỉ định kiểu ErrorconsterrorEvent :MyErrorEvent = {error : newError ("エラーです"),type : "syntax",};constnetworkErrorEvent :MyErrorEvent <NetworkError > = {error : newNetworkError ("ネットワークエラーです"),type : "network",};
ts// Nhờ chỉ định default type parameter, có thể bỏ qua chỉ định kiểu ErrorconsterrorEvent :MyErrorEvent = {error : newError ("エラーです"),type : "syntax",};constnetworkErrorEvent :MyErrorEvent <NetworkError > = {error : newNetworkError ("ネットワークエラーです"),type : "network",};
Kết hợp với type parameter constraint
Bạn cũng có thể kết hợp việc chỉ định kiểu là subtype của một kiểu nào đó với việc chỉ định default type khi bỏ qua. Về type parameter constraint, có trang chuyên biệt, vui lòng tham khảo.
📄️ Type parameter constraint
Trong TypeScript, có thể giới hạn type parameter của generics vào một kiểu cụ thể.
Nếu muốn giới hạn kiểu T được truyền vào MyErrorEvent là subclass của Error, đồng thời khi bỏ qua thì mặc định là SyntaxError, cú pháp như sau:
tstypeMyErrorEvent <T extendsError =SyntaxError > = {error :T ;type : string;};
tstypeMyErrorEvent <T extendsError =SyntaxError > = {error :T ;type : string;};
Khi kết hợp type parameter constraint và default type parameter, default type parameter phải thỏa mãn constraint.
tsinterfaceType 'bigint' does not satisfy the constraint 'string | number'.2344Type 'bigint' does not satisfy the constraint 'string | number'.Serializable <T extends string | number =bigint > {value :T ;toString (): string;}
tsinterfaceType 'bigint' does not satisfy the constraint 'string | number'.2344Type 'bigint' does not satisfy the constraint 'string | number'.Serializable <T extends string | number =bigint > {value :T ;toString (): string;}
Ví dụ này constraint kiểu string | number nhưng lại chỉ định bigint làm default type parameter. Do đó không thỏa mãn constraint và TypeScript sẽ báo lỗi.
Chỉ định default type parameter bằng generics
Khi có nhiều generics, có thể chỉ định default type parameter bằng default type parameter khác.
tsclassAubergine <A ,B =A ,C =B > {private readonlya :A ;private readonlyb :B ;private readonlyc :C ;public constructor(a :A ,b :B ,c :C ) {this.a =a ;this.b =b ;this.c =c ;}// ...}
tsclassAubergine <A ,B =A ,C =B > {private readonlya :A ;private readonlyb :B ;private readonlyc :C ;public constructor(a :A ,b :B ,c :C ) {this.a =a ;this.b =b ;this.c =c ;}// ...}
Default type parameter được tham chiếu từ trái sang phải, nên generics bên trái không thể chỉ định generics bên phải.
tsclassType parameter defaults can only reference previously declared type parameters.Aubergine <A =, B , B C =B > {
Required type parameters may not follow optional type parameters.2744
2706Type parameter defaults can only reference previously declared type parameters.
Required type parameters may not follow optional type parameters.private readonlya :A ;private readonlyb :B ;private readonlyc :C ;public constructor(a :A ,b :B ,c :C ) {this.a =a ;this.b =b ;this.c =c ;}}
tsclassType parameter defaults can only reference previously declared type parameters.Aubergine <A =, B , B C =B > {
Required type parameters may not follow optional type parameters.2744
2706Type parameter defaults can only reference previously declared type parameters.
Required type parameters may not follow optional type parameters.private readonlya :A ;private readonlyb :B ;private readonlyc :C ;public constructor(a :A ,b :B ,c :C ) {this.a =a ;this.b =b ;this.c =c ;}}