Record<Keys, Type>
Record<Keys, Type> là utility type tạo object type với property key là Keys và property value là Type.
Type argument của Record<Keys, Type>
Keys
Chỉ định property key của object. Kiểu có thể gán cho Keys là string, number, symbol và literal type của chúng.
Type
Chỉ định kiểu của property value của object. Có thể gán bất kỳ kiểu nào.
Ví dụ sử dụng Record
Định nghĩa index type với key là string và value là number:
tstypeStringNumber =Record <string, number>;constvalue :StringNumber = {a : 1,b : 2,c : 3 };
tstypeStringNumber =Record <string, number>;constvalue :StringNumber = {a : 1,b : 2,c : 3 };
Định nghĩa object type với key là firstName, middleName, familyName và value là string:
tstypePerson =Record <"firstName" | "middleName" | "lastName", string>;constperson :Person = {firstName : "Robert",middleName : "Cecil",lastName : "Martin",};
tstypePerson =Record <"firstName" | "middleName" | "lastName", string>;constperson :Person = {firstName : "Robert",middleName : "Cecil",lastName : "Martin",};
Lưu ý về index access
Khi chỉ định kiểu không phải literal type như string cho key như Record<string, ...>, cần chú ý về index access. Bởi vì ngay cả khi truy cập key không tồn tại, nó vẫn được xử lý như thể key đó luôn tồn tại.
Trong ví dụ sau, object dict có kiểu Record<string, number> có key a nhưng không có key b. Tuy nhiên, dict.b vẫn được suy luận là number.
tsconstdict :Record <string, number> = {a : 1 };dict .b ;
tsconstdict :Record <string, number> = {a : 1 };dict .b ;
Giá trị thực tế của dict.b là undefined, nên nếu gọi method của dict.b sẽ gây lỗi runtime.
tsconstdict :Record <string, number> = {a : 1 };console .log (dict .b );dict .b .toFixed (); // 実行時エラーが発生する
tsconstdict :Record <string, number> = {a : 1 };console .log (dict .b );dict .b .toFixed (); // 実行時エラーが発生する
Hành vi này không thuận lợi cho các developer muốn giảm runtime error thông qua type checking.
Để giải quyết vấn đề này, TypeScript cung cấp compiler option noUncheckedIndexedAccess. Khi bật option này, kết quả của index access sẽ có kiểu T | undefined. Tức là kiểu này sẽ xem xét khả năng là undefined. Do đó, code gọi method của dict.b sẽ gây compile error và bạn có thể hưởng lợi từ type checking.
tsconstdict :Record <string, number> = {a : 1 };dict .b ;'dict.b' is possibly 'undefined'.18048'dict.b' is possibly 'undefined'.dict .b .toFixed ();
tsconstdict :Record <string, number> = {a : 1 };dict .b ;'dict.b' is possibly 'undefined'.18048'dict.b' is possibly 'undefined'.dict .b .toFixed ();
📄️ noUncheckedIndexedAccess
Bắt buộc check undefined khi tham chiếu property của index type hoặc phần tử array
Mặt khác, khi key của Record chỉ bao gồm literal type như "firstName" | "lastName", vấn đề này không xảy ra bất kể cài đặt noUncheckedIndexedAccess. Vì key bị giới hạn, truy cập key không tồn tại sẽ gây compile error.
ts// noUncheckedIndexedAccessがfalseの場合typePerson =Record <"firstName" | "lastName", string>;constperson :Person = {firstName : "Robert",lastName : "Martin",};constfirstName =person .firstName ;Property 'b' does not exist on type 'Person'.2339Property 'b' does not exist on type 'Person'.person .; // 存在しないキーへのアクセス b
ts// noUncheckedIndexedAccessがfalseの場合typePerson =Record <"firstName" | "lastName", string>;constperson :Person = {firstName : "Robert",lastName : "Martin",};constfirstName =person .firstName ;Property 'b' does not exist on type 'Person'.2339Property 'b' does not exist on type 'Person'.person .; // 存在しないキーへのアクセス b
Khi key là string, nếu bật noUncheckedIndexedAccess, compiler sẽ bao gồm undefined, nhưng khi key là literal type (hoặc union của literal type), compiler sẽ không bao gồm undefined. Bởi vì việc key luôn tồn tại đã tự rõ ràng do việc chỉ định key bằng literal type.
ts// noUncheckedIndexedAccessがtrueの場合typePerson =Record <"firstName" | "lastName", string>;constperson :Person = {firstName : "Robert",lastName : "Martin",};constfirstName =person .firstName ; // undefinedは含まれない
ts// noUncheckedIndexedAccessがtrueの場合typePerson =Record <"firstName" | "lastName", string>;constperson :Person = {firstName : "Robert",lastName : "Martin",};constfirstName =person .firstName ; // undefinedは含まれない
Thông tin liên quan
📄️ Index signature
Trong TypeScript, có trường hợp muốn chỉ định type của property mà không chỉ định tên field của object. Lúc này có thể sử dụng index signature. Ví dụ, object có tất cả property là type number được type annotation như sau.
📄️ Mapped Types
Với index type, bạn có thể tự do thiết lập bất kỳ key nào khi gán giá trị, nhưng khi truy cập phải kiểm tra undefined mỗi lần. Nếu format input đã được xác định rõ ràng, bạn có thể cân nhắc sử dụng Mapped Types.
📄️ Map<K, V>
Map là một trong những built-in API của JavaScript, là object để xử lý cặp key-value. Trong Map, một key chỉ có thể lưu trữ một giá trị duy nhất.