تایپاسکریپت - آیا T[keyof T] مانند نوع شرطی توزیعی کار میکند؟
من در تلاش هستم این مثال از بخش نوعهای شرطی توزیعی را درک کنم:
نوعهای شرطی زمانی که با نوعهای نگاشته شده ترکیب میشوند، بهویژه مفید هستند:
type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T];
استفاده از عملگر دسترسی به شاخص برای من در این مثال روشن نیست. در اینجا سادهترین مثالی که از همان ایده استفاده میکند (تا جایی که من میتوانم بفهمم) آمده است:
type Foo = {
prop1: never;
prop2: never
method1: "method1";
method2: "method2";
}
type FunctionPropertyNames = Foo[keyof Foo] // "method1" | "method2"
پس، سؤال من این است: آیا چنین استفادهای از عملگر دسترسی به اندیس فقط یک مورد خاص از نوع شرطی توزیعی است؟ چون به نظر میرسد نوع نتیجه، اجتماع تمام کاربردهای T[K] است که در آن never فیلتر شده است، زیرا "never اجتماع خالی است"
بهروزرسانی. من سعی میکنم این سؤال را بهطور دقیقتر بیان کنم: راهنمای TS توضیح میدهد که نحو انواع نگاشتی و انواع شرطی چیست. با این حال، من هیچ توضیحی درباره این شکل از تعریف نوع پیدا نکردم:
type Keys = 'name1' | 'name2' | 'name3'
type Foo = Bar[Keys]
یا، واقعبینانهتر:
type Foo = Bar[keyof Bar]
به نظر میرسد نوعی نگاشت باشد، اما همچنین فیلتر کردن را نیز فراهم میکند، در صورتی که Keys شامل never باشد. بنابراین سوال من بیشتر در مورد این بود که آیا توضیح دقیقی از این ویژگی سیستم نوع TS وجود دارد یا خیر.
پاسخ شماره ۱
این یک استفاده خاص است که وقتی صحبت از فیلتر کردن ویژگیهای یک شیء/کلاس بر اساس نوع ویژگیها میشود، قدرتمند است. این مقاله به خوبی توضیح میدهد که چگونه فیلتر کردن یک اجتماع کلاسها بر اساس اینکه آیا آنها یک متد را پیادهسازی میکنند یا نه، راحت است (ببینید بخش Refining unions with distributive conditional types مقاله).
استفاده دیگر
همانطور که گفتید، مزیت این استفاده از عملگر دسترسی شاخص این است که کمک میکند انواع غیرمرتبط از یک اتحاد حذف شوند، اما مزایای دیگری نیز دارد، مانند تغییر یک نوع بر اساس شرایط خاص.
در اینجا یک نمونه است:
type SchemaType<T> = {
[k in keyof T]: T[k] extends
| string
| number
| boolean
| Types.ObjectId
| Client
| Doer
| Mission
| Date
| Array<any>
? SchemaDefinition['']
: SchemaType<T[k]>;
};
این یک نوع است که من برای تایپ اسناد مانگوس خود استفاده میکنم.
من یک interface در تایپاسکریپت دارم که تعریف میکند User چیست و یک document که سند را در mongoDb توصیف میکند.
من چیزی که میخواستم این بود که document همان سلسلهمراتب interface را پیادهسازی کند.
به عنوان مثال، اگر User دارای ساختار باشد:
interface User {
id: Types.ObjectId;
profile: {
first_name: string;
}
}
من میخواستم document همان مورد را اعمال کند و نوع آن ایمن باشد:
const schema: SchemaType<User> = {
id: { type: Types.ObjectId },
profile: {
first_name: { type: String, default: '' },
},
};
این کاری است که SchemaType با عملگر دسترسی به ایندکس انجام میدهد. اگر ویژگی به عنوان نوع برگ در نظر گرفته شود (مثل id و first_name)، پس باید به صورت SchemaDefinition در سند تایپ شود. اگر یک شیء باشد، پس باید همانطور که در interface است تایپ شود (این همان کاری است که SchemaType<T[k]> انجام میدهد).
