typescript - چرا محدود کردن نوع داخل closures برای اشیای دارای ویژگیها عمل نمیکند اما برای متغیرهای اعلام شده کار میکند؟
من در تلاش هستم بفهمم چرا تایپاسکریپت نمیتواند بهدرستی نوع یک پارامتر ویژگی شیء را که ممکن است undefined باشد، در داخل یک تابع داخلی تشخیص دهد، اما وقتی همان ویژگی به متغیر خودش در دامنه تابع بیرونی اختصاص داده میشود، محدودسازی نوع بهصورت روان انجام میشود.
من این قطعه کد را دارم تا مشکل را بازتولید کنم:
type MyType = {
optional?: string
}
(arr: string[], param: MyType) => {
if (param.optional) {
const includes = arr.includes(param.optional) // <-- Fine
arr.filter(function (item) {
return item.includes(param.optional) // <-- Wrong! Type undefined is not assignable...
})
}
}
در داخل شاخه if، تایپاسکریپت در مورد استفاده از param.optional در داخل تابع داخلی filter به من هشدار میدهد زیرا ممکن است string | undefined باشد، در حالی که هنگامی که از آن در arr.includes(param.optional) استفاده میشود، هیچ هشداری وجود ندارد.
این برای من خیلی عجیب به نظر میرسد زیرا اگر به جای استفاده از param.optional همان مقدار را به متغیر خودش اختصاص دهم، تایپاسکریپت قادر است نوع آن (string) را به طور کامل محدود کند.
type MyType = {
optional?: string
}
(arr: string[], param: MyType) => {
const variable = param.optional
if (variable) {
const includes = arr.includes(variable) // <-- Fine
arr.filter(function (item) {
return item.includes(variable) // <-- Fine
})
}
}
چرا این رفتار اتفاق میافتد؟ این چه ربطی به خود شیء دارد (زیرا اگر پارامتر فقط یک مقدار اولیه اختیاری string | undefined باشد، این مشکل رخ نمیدهد)؟
پاسخ شماره ۱
زیرا در حالت کلی امن نیست که این کار انجام شود.
TypeScript نمیداند filter چه کاری انجام میدهد، بنابراین نمیداند چه زمانی کالبک آن فراخوانی میشود (همزمان الان، یا ناهمزمان بعداً) و بنابراین نمیداند آیا شیء توسط کد دیگری خارج از محدوده تابع تغییر میکند یا نه. تغییرات توسط کد خارج از تابع میتواند محافظ نوع را نامعتبر کند.
اما با ثابت variable شما (که نام خندهداری دارد)، TypeScript میداند که مقدار نمیتواند تغییر کند، بنابراین میتوان محافظ نوع را اعمال کرد. حتی اگر به جای const از let استفاده کنید هم کار میکند، زیرا TypeScript میتواند ببیند هیچ انتسابی به variable انجام نمیشود. (اما اگر از let استفاده میکردید و بعد از فراخوانی filter نوشتید variable=undefined;، همان خطایی که با param.optional دریافت میکنید را دریافت میکردید، زیرا دوباره TypeScript نمیداند کد callback نسبت به آن انتساب کی اجرا میشود: مثال.)