راهنمای جامع برای درک نوع رکورد TypeScript
نوع Record
TypeScript مدیریت ساختارهای شی را با انواع مقادیر سازگار ساده می کند. این راهنما ملزومات Record
را پوشش میدهد، از جمله تعریف، نحو، و تفاوت آن با انواع دیگر مانند تاپل. ما یاد خواهیم گرفت که چگونه Record
در سناریوهای عملی مانند اعمال مدیریت جامع پرونده و نگاشت enums تعریف و استفاده کنیم. علاوه بر این، با ترکیب Record
با انواع ابزاری مانند Partial
، Pick
و Readonly
، کاربردهای پیشرفته را تحلیل خواهیم کرد.
مقدمه
نوع Record
یک نوع کاربردی است که به ما امکان می دهد یک نوع شی با کلیدهای مشخص شده و یک نوع مقدار یکنواخت ایجاد کنیم. این نوع به ویژه برای تعریف نگاشت ها و حصول اطمینان از مطابقت تمام مقادیر موجود در یک شی با یک نوع مفید است.
تعریف نوع رکورد
تعریف رسمی از اسناد TypeScript این است:
Record < Keys , Type >
اینجا:
Keys
مجموعهای از کلیدها را در رکورد نشان میدهند که میتواند ترکیبی از حرفهای رشتهای یا نوعی مشتق شده از یک اتحادیه باشد.
Type
، نوع مقادیر مرتبط با آن کلیدها است.
به عنوان مثال، Record<string, number>
یک شی را تعریف می کند که در آن هر کلید یک رشته و هر مقدار یک عدد است. این نوع تضمین می کند که تمام ویژگی های شی دارای یک نوع مقدار هستند، اما کلیدها می توانند متفاوت باشند.
مقایسه بین یک رکورد و یک تاپل
هم Record
و هم تاپل ها برای مدیریت مجموعه داده ها استفاده می شوند، اما اهداف متفاوتی دارند. حتی زمانی که مقادیر متعددی را ذخیره می کنند، در ساختار و کاربرد متفاوت هستند. یک رکورد خصوصیات را با یک نوع ثابت نامگذاری می کند، در حالی که یک تاپل فهرست مرتبی از عناصر است که با موقعیت آنها مشخص می شود. در اینجا یک مقایسه ساده وجود دارد:
ضبط کنید . یک نوع شی ایجاد می کند که در آن همه مقادیر دارای یک نوع هستند، اما کلیدها می توانند انعطاف پذیر باشند. این برای نگاشت کلیدها به مقادیر و اطمینان از اینکه همه کلیدها به یک نوع خاص پایبند هستند مفید است.
چندتایی . آرایه ای را با تعداد ثابتی از عناصر تعریف می کند که در آن هر عنصر می تواند نوع متفاوتی داشته باشد. تاپل ها زمانی استفاده می شوند که به یک مجموعه با اندازه ثابت با انواع خاص برای هر موقعیت نیاز داریم.
برای مثال موارد زیر را در نظر بگیرید.
در اینجا یک نوع Record
وجود دارد که کلیدهای رشته ای را به مقادیر اعداد نگاشت می کند:
type AgeMap = Record < string , number > ;
یک نوع تاپل آرایه ای را با یک رشته (نام) و یک عدد (سن) در یک موقعیت ثابت نشان می دهد:
type Person = [ string , number ] ;
استفاده اولیه از نوع رکورد
نوع Record
یک راه ساده و کارآمد برای نگاشت کلیدها به مقادیر ارائه می دهد. این به ویژه زمانی مفید است که ما نیاز به تعریف اشیاء با جفت های کلید-مقدار خاص داریم که در آن کلیدها از نوع خاصی هستند و مقادیر از نوع دیگری هستند.
در اینجا چند روش اساسی برای استفاده از نوع Record
برای تعریف و ایجاد داده های ساخت یافته وجود دارد.
تعریف رکورد
برای تعریف یک Record
، انواع کلیدها و مقادیر را مشخص می کنیم. مثال زیر یک شی را تعریف می کند که در آن هر کلید یک رشته است و هر مقدار نیز یک رشته است. این می تواند برای یک نقشه عمومی از داده های کاربر استفاده شود:
type User = Record < string , string > ;
ایجاد یک مثال نوع Record
برخی از وب سایت ها دارای زیر دامنه های مختلفی هستند. بیایید فرض کنیم هر یک از این زیردامنه ها به سطحی از دسترسی ادمین نیاز دارند و یک نوع Record
برای ذخیره نقش های مختلف مدیریت و سطوح دسترسی متناظر آنها ایجاد کنیم. در اینجا، UserRoles
و UserStatus
انواع Record
هستند که در آن کلیدها حروف رشتهای خاص هستند ( admin
، blogAdmin
، docsAdmin
، active
، inactive
، suspended
)، و مقادیر رشتههایی هستند که هر نقش و وضعیت را توصیف میکنند.
ابتدا یک UserRoles
از نوع Record
با نقش های مدیر خاص به عنوان کلید و توضیحات آنها به عنوان مقادیر تعریف می کنیم. نوع UserRoles
تضمین میکند که هر شیء از این نوع دارای کلیدهای admin
، blogAdmin
، و docsAdmin
است که مقادیر رشتهای هر نقش را توصیف میکنند. شی roles
با ارائه توضیحات برای هر نقش مدیر به این نوع پایبند است:
type UserRoles = Record < 'admin' | 'blogAdmin' | 'docsAdmin' , string > ; const roles : UserRoles = { admin : 'General Administrator with access to all areas.' , blogAdmin : 'Administrator with access to blog content.' , docsAdmin : 'Administrator with access to documentation.' } ;
در مرحله بعد، یک نوع Record
UserStatus
با وضعیت های خاص به عنوان کلید و توضیحات آنها به عنوان مقادیر تعریف می کنیم. نوع UserStatus
تضمین می کند که هر شیء از این نوع دارای کلیدهای active
، inactive
و suspended
خواهد بود، با مقادیر رشته ای که هر وضعیت را توصیف می کند. شی userStatus
با ارائه توضیحات برای هر وضعیت به این نوع پایبند است:
type UserStatus = Record < 'active' | 'inactive' | 'suspended' , string > ; const userStatus : UserStatus = { active : 'User is currently active and can use all features.' , inactive : 'User is currently inactive and cannot access their account.' , suspended : 'User account is suspended due to policy violations.' } ;
با ایجاد انواع Record
به این روش، ما اطمینان میدهیم که نقشهای مدیر و وضعیتهای کاربر به خوبی تعریف شده و در سراسر برنامه سازگار هستند.
موارد استفاده عملی از نوع رکورد
در این بخش، چندین مورد استفاده عملی از نوع Record
را تحلیل خواهیم کرد تا تطبیق پذیری و اثربخشی آن را در سناریوهای مختلف نشان دهیم.
استفاده از مورد 1: اجرای رسیدگی جامع پرونده
استفاده از Record
برای تعریف نگاشت بین مقادیر مورد و پیام ها به ما این امکان را می دهد که هر مورد ممکن را به صراحت مدیریت کنیم. این تضمین می کند که همه موارد تحت پوشش قرار می گیرند و موارد از دست رفته منجر به خطاهای زمان کامپایل می شود.
در مثال زیر، statusMessages
یک Record
است که در آن کلیدها مقادیر خاصی Status
هستند ( 'pending'
، 'completed'
، 'failed'
) و هر کلید به یک پیام مربوطه نگاشت می شود. تابع getStatusMessage
از این رکورد برای برگرداندن پیام مناسب بر اساس پارامتر status
استفاده می کند. این رویکرد تضمین می کند که همه وضعیت ها به درستی و به طور مداوم مدیریت می شوند.
مثال:
type Status = 'pending' | 'completed' | 'failed' ; interface StatusInfo { message : string ; severity : 'low' | 'medium' | 'high' ; retryable : boolean ; } const statusMessages : Record < Status , StatusInfo > = { pending : { message : 'Your request is pending.' , severity : 'medium' , retryable : true , } , completed : { message : 'Your request has been completed.' , severity : 'low' , retryable : false , } , failed : { message : 'Your request has failed.' , severity : 'high' , retryable : true , } , } ; function getStatusMessage ( status : Status ) : string { const info = statusMessages [ status ] ; return ` ${ info . message } Severity: ${ info . severity } , Retryable: ${ info . retryable } ` ; } console . log ( getStatusMessage ( 'completed' ) ) ;
استفاده از مورد 2: اعمال تحلیل نوع در برنامه ها با استفاده از Generics
ژنریک ها در TypeScript کدهای انعطاف پذیر و قابل استفاده مجدد را امکان پذیر می کنند. وقتی با Record
ترکیب میشود، ژنریکها میتوانند به تحلیل نوع کمک کنند و اطمینان حاصل کنند که اشیا با ساختارهای خاص مطابقت دارند.
با استفاده از Generics با Record
، میتوانیم توابع یا ابزارهایی ایجاد کنیم که اشیایی را با مجموعهای از کلیدها و یک نوع مقدار ثابت تولید میکنند. این رویکرد ایمنی نوع و قابلیت استفاده مجدد را در پایگاه کد ما افزایش می دهد.
در مثال زیر، تابع createRecord
آرایه ای از کلیدها و یک مقدار را می گیرد و یک Record
برمی گرداند که در آن هر کلید به مقدار ارائه شده نگاشت می شود. این تابع از ژنریک ( K
برای کلیدها و T
برای نوع مقدار) استفاده می کند تا اطمینان حاصل شود که Record
حاصل از ساختار صحیحی برخوردار است.
مثال:
function createRecord < K extends string , T > ( keys : K [ ] , value : T ) : Record < K , T > { const record : Partial < Record < K , T >> = { } ; keys . forEach ( key => record [ key ] = value ) ; return record as Record < K , T > ; } interface RoleInfo { description : string ; permissions : string [ ] ; } const userRoles = createRecord ( [ 'admin' , 'editor' , 'viewer' ] , { description : 'Default role' , permissions : [ 'read' ] , } ) ; console . log ( userRoles ) ;
استفاده از مورد 3: نگاشت Enums به داده
استفاده از Record
برای نگاشت enum ها به داده ها به ما امکان می دهد یک جدول جستجو ایجاد کنیم که در آن هر مقدار enum با اطلاعات خاصی مرتبط باشد. این به ویژه برای سناریوهایی مانند پیکربندی تنظیمات بر اساس مقادیر enum مفید است.
در این مثال، colorHex
یک Record
است که هر مقدار Color
را به کد رنگ هگزا دسیمال مربوطه نگاشت می کند. این رویکرد روشی واضح و ایمن برای مدیریت داده های مربوط به رنگ بر اساس مقادیر enum ارائه می دهد.
مثال:
enum Color { Red = 'RED' , Green = 'GREEN' , Blue = 'BLUE' , Yellow = 'YELLOW' } interface ColorInfo { hex : string ; rgb : string ; complementary : string ; } const colorHex : Record < Color , ColorInfo > = { [ Color . Red ] : { hex : '#FF0000' , rgb : 'rgb(255, 0, 0)' , complementary : '#00FFFF' , } , [ Color . Green ] : { hex : '#00FF00' , rgb : 'rgb(0, 255, 0)' , complementary : '#FF00FF' , } , [ Color . Blue ] : { hex : '#0000FF' , rgb : 'rgb(0, 0, 255)' , complementary : '#FFFF00' , } , [ Color . Yellow ] : { hex : '#FFFF00' , rgb : 'rgb(255, 255, 0)' , complementary : '#0000FF' , } , } ; console . log ( colorHex [ Color . Green ] ) ;
استفاده از مورد 4: ایجاد جداول جستجو
جدول جستجو با استفاده از Record
به نگاشت کلیدها (مانند شناسه ها، نام ها) به مقادیر خاص (مانند توضیحات، کدها) کمک می کند. این می تواند برای برنامه های مختلف از جمله تنظیمات، ترجمه و بسیاری موارد دیگر مفید باشد.
در اینجا، countryCode
یک Record
است که کد کشورها را به نام کشورها، جمعیت، پایتخت ها و قاره های مربوطه نگاشت می کند. این جدول جستجو امکان بازیابی سریع و ایمن اسامی کشورها و جمعیت ها را بر اساس کد کشورها فراهم می کند.
مثال:
type CountryCode = "US" | "CA" | "MX" | "JP" ; interface CountryInfo { name : string ; population : number ; capital : string ; continent : string ; } const countryLookup : Record < CountryCode , CountryInfo > = { US : { name : "United States" , population : 331000000 , capital : "Washington DC" , continent : "North America" , } , CA : { name : "Canada" , population : 37700000 , capital : "Ottawa" , continent : "North America" , } , MX : { name : "Mexico" , population : 128000000 , capital : "Mexico City" , continent : "North America" , } , JP : { name : "Japan" , population : 126300000 , capital : "Tokyo" , continent : "Asia" , } , } ; console . log ( countryLookup . US ) ; console . log ( countryLookup . US . population ) ;
تکرار بیش از انواع Record
تکرار بر روی انواع Record
برای دسترسی و دستکاری داده ها در ساختارهای داده مهم است. بیایید یک داده نمونه ایجاد کنیم و روشهای مختلفی را نشان دهیم که چگونه میتوانیم روی انواع Record
TypeScript تکرار کنیم.
داده های نمونه:
interface Course { professor : string ; credits : number ; students : string [ ] ; } interface Courses { [ key : string ] : Course ; } const courses : Courses = { Math101 : { professor : "Dr. Eze" , credits : 3 , students : [ "Emmanuel" , "Bob" , "Charlie" ] , } , History201 : { professor : "Dr. Jones" , credits : 4 , students : [ "Dave" , "Eve" ] , } , } ;
با استفاده از forEach
. برای استفاده از forEach
با یک Record
، آن را به آرایه ای از جفت های کلید-مقدار تبدیل کنید:
Object . entries ( courses ) . forEach ( ( [ key , value ] ) => { console . log ( ` ${ key } : ${ value . professor } , ${ value . credits } ` ) ; value . students . forEach ( student => { console . log ( ` Student: ${ student } ` ) ; } ) ; } ) ;
استفاده for...in
. حلقه for...in
روی کلیدهای یک Record
تکرار می شود:
for ( const key in courses ) { if ( courses . hasOwnProperty ( key ) ) { const course = courses [ key ] ; console . log ( ` ${ key } : ${ course . professor } , ${ course . credits } ` ) ; course . students . forEach ( student => { console . log ( ` Student: ${ student } ` ) ; } ) ; } }
با استفاده از Object.keys()
. Object.keys()
آرایه ای از کلیدهای Record
را برمی گرداند:
Object . keys ( courses ) . forEach ( ( key ) => { const course = courses [ key ] ; console . log ( ` ${ key } : ${ course . professor } , ${ course . credits } ` ) ; course . students . forEach ( student => { console . log ( ` Student: ${ student } ` ) ; } ) ; } ) ;
استفاده از Object.values()
. Object.values()
آرایه ای از مقادیر Record
را برمی گرداند:
Object . values ( courses ) . forEach ( ( course ) => { console . log ( ` ${ course . professor } , ${ course . credits } ` ) ; course . students . forEach ( student => { console . log ( ` Student: ${ student } ` ) ; } ) ; } ) ;
استفاده پیشرفته و انواع ابزار با Record
نوع Record
را می توان با سایر انواع ابزار ترکیب کرد تا به انعطاف پذیری و ایمنی بیشتر دست یابد. این بخش الگوهای استفاده پیشرفته را نشان میدهد و نشان میدهد که چگونه Record
میتواند با انواع ابزاری مانند Pick
، Readonly
و Partial
کار کند.
ترکیب Record
با Pick
برای نگاشت نوع انتخابی
نوع ابزار Pick
به ما اجازه می دهد تا با انتخاب ویژگی های خاص از یک نوع موجود، یک نوع جدید ایجاد کنیم. این زمانی مفید است که بخواهیم فقط با زیرمجموعه ای از ویژگی های یک نوع بزرگتر کار کنیم.
در اینجا، با انتخاب تنها name
و آپشن های price
از رابط ProductInfo
، و سپس با استفاده از Record
برای نگاشت محصولات مختلف به این نوع جدید، نوع جدیدی SelectedProductInfo
ایجاد کردیم:
interface ProductInfo { name : string ; price : number ; category : string ; } type SelectedProductInfo = Pick < ProductInfo , "name" | "price" > ; type Product = 'Laptop' | 'Smartphone' | 'Tablet' ; const products : Record < Product , SelectedProductInfo > = { "Laptop" : { name : "Dell XPS 15" , price : 1500 } , "Smartphone" : { name : "iPhone 12" , price : 999 } , "Tablet" : { name : "iPad Pro" , price : 799 } } ;
ترکیب Record
با Readonly
برای آپشن های غیرقابل تغییر
نوع ابزار Readonly
تضمین می کند که ویژگی ها پس از تنظیم نمی توانند تغییر یابند. این برای ایجاد ساختارهای داده تغییرناپذیر مفید است.
بیشتر بخوانید
متا برای پیروی از دستور ممنوعیت به اشتراک گذاری داده با اینستاگرام، Threads را در ترکیه می بندد
نوع ReadonlyProductInfo
در مثال زیر همه ویژگی های ProductInfo
را غیرقابل تغییر می کند و اطمینان می دهد که جزئیات هر محصول پس از تعریف نمی تواند تغییر کند:
type ReadonlyProductInfo = Readonly < ProductInfo > ; const readonlyProducts : Record < Product , ReadonlyProductInfo > = { "Laptop" : { name : "Dell XPS 15" , price : 1500 , category : "Electronics" } , "Smartphone" : { name : "iPhone 12" , price : 999 , category : "Electronics" } , "Tablet" : { name : "iPad Pro" , price : 799 , category : "Electronics" } } ;
ترکیب Record
با Partial
برای ویژگی های اختیاری
نوع کاربردی Partial
، تمام خصوصیات یک نوع را اختیاری می کند. این برای سناریوهایی مفید است که ممکن است همه ویژگی ها به طور همزمان شناخته یا مورد نیاز نباشند.
در اینجا، نوع PartialProductInfo
به ما اجازه میدهد تا محصولاتی با برخی یا هیچکدام از آپشن های تعریفشده در ProductInfo
ایجاد کنیم، که انعطافپذیری در نحوه تعیین اطلاعات محصول فراهم میکند:
type PartialProductInfo = Partial < ProductInfo > ; const partialProducts : Record < Product , PartialProductInfo > = { "Laptop" : { name : "Dell XPS 15" } , "Smartphone" : { price : 999 } , "Tablet" : { } } ;
ترکیب Record
با Record
برای نگاشت تودرتو
یکی دیگر از کاربردهای پیشرفته شامل ترکیب انواع Record
برای ایجاد نگاشت های تودرتو است که می تواند به ویژه برای مدیریت ساختارهای داده پیچیده مفید باشد.
در این مثال، storeInventory
از انواع Record
تودرتو برای نگاشت بخش ها به محصولات و جزئیات مربوطه استفاده می کند و نشان می دهد که چگونه Record
می تواند برای مدیریت داده های پیچیده تر ترکیب شود:
type Department = 'Electronics' | 'Furniture' ; type ProductDetails = Record < Product , ProductInfo > ; const storeInventory : Record < Department , ProductDetails > = { "Electronics" : { "Laptop" : { name : "Dell XPS 15" , price : 1500 , category : "Electronics" } , "Smartphone" : { name : "iPhone 12" , price : 999 , category : "Electronics" } , "Tablet" : { name : "iPad Pro" , price : 799 , category : "Electronics" } } , "Furniture" : { "Chair" : { name : "Office Chair" , price : 200 , category : "Furniture" } , "Table" : { name : "Dining Table" , price : 500 , category : "Furniture" } , "Sofa" : { name : "Living Room Sofa" , price : 800 , category : "Furniture" } } } ;
نتیجه گیری
نوع Record
ابزاری همه کاره برای مدیریت و ساختاربندی انواع شی است زیرا به ما امکان میدهد تا نگاشتهای واضحی را بین کلیدها و مقادیر تعریف کنیم و از ایمنی نوع و سازگاری در کد خود اطمینان حاصل کنیم.
برای اطلاعات دقیق تر، به مستندات TypeScript مراجعه کنید و سایر منابع اضافی مانند Total TypeScript و TypeScript Tutorial را مرور کنید تا درک خود را از سیستم نوع Record
TypeScript عمیق تر کنید.
ارسال نظر