در تایپاسکریپت، آیا ممکن است یک مقدار از نوع any را به یک نوع سفارشی تبدیل کرده و در صورت ناهماهنگی مقدار، از مقدار پیشفرض استفاده کرد؟
بگو من یک نوع مثل دارم
type MyType = "value1" | "value2"
و من یک مقدار x از نوع any دارم. آیا راهی وجود دارد که x را به MyType تبدیل کنیم به گونهای که در صورتی که مقدار x با نوع MyType مطابقت نداشته باشد، یک مقدار پیشفرض مشخص d برگردانده شود، و به طوری که کامپایلر TS آن را تایپبندی کند؟
چیزی شبیه به:
let y: MyType = magicThatDoesWhatIWant(x, MyType, d)
این سپس به طور مؤثر چیزی شبیه کد JS زیر تولید خواهد کرد (پس از کامپایل):
let y;
switch (x) {
case "value1":
y = x
break;
case "value2":
y = x
break;
default:
y = d
}
آیا چیزی شبیه این در TS وجود دارد؟
پاسخ شماره ۱
آنچه شما به دنبال آن هستید یک نگهبان نوع تعریف شده توسط کاربر است تا نوع یک متغیر any را اعتبارسنجی کند. شما میتوانید این را با تعیین یک مقدار جایگزین ترکیب کنید.
شما نمیتوانید MyType را به عنوان آرگومان به یک تابع پاس دهید زیرا نوعهای typescript در زمان اجرا وجود ندارند و بنابراین نمیتوان از آنها به عنوان متغیر استفاده کرد. شما میتوانید آنچه را میخواهید به دست آورید اگر MyType از یک متغیر مشتق شده باشد، زیرا میتوانید از آن متغیر برای بررسی در زمان اجرا استفاده کنید.
از یک آرایه
ما یک ثابت تغییرناپذیر با مقادیر نوع خود اعلام میکنیم:
const strings = [ "value1", "value2" ] as const;
ما میگوییم که MyType نوع عناصر آن آرایه است:
type MyType = (typeof strings)[number];
این نگهبان نوع ما است. اگر متغیر any به نام x در آرایهای قرار داشته باشد که تمام مقادیر آن از نوع T هستند، آنگاه ما تأیید میکنیم که x از نوع T است.
function isInArray<T>(x: any, values: readonly T[]): x is T {
return values.includes(x);
}
حالا نوبت «جادوی» شماست. ما باید یک آرایه از values برای بررسی و همچنین یک مقدار پیشفرض d ارسال کنیم. ما خواهیم دانست که هر مقداری که برگردانیم دارای نوع T است.
function castToType<T>(x: any, values: readonly T[], d: T): T {
return isInArray(x, values) ? x : d;
}
هر دو v1 و v3 در این مثال دارای نوع "value1" | "value2" هستند. v1 برابر "value1" است زیرا آن رشته با نوع ما مطابقت داشت. v3 برابر "value2" است که مقدار پیشفرض بود.
const v1 = castToType("value1", strings, "value2")
const v3 = castToType("value3", strings, "value2")
لینک محیط بازی Typescript
از یک Enum
روش آرایه با هر نوع اتحادیه کار می کند. اگر مقادیر شما string یا number هستند، میcتوانید از enums TypeScript استفاده کنید زیرا هم یک اعلان نوع و هم یک متغیر شی ایجاد میcکنند که میcتوانیم در زمان اجرا استفاده کنیم.
enum MyEnum {
Value1 = "value1",
Value2 = "value2",
}
ما اساساً به همان روش چک میکنیم، با این تفاوت که از Object.values برای گرفتن یک آرایه از مقادیر معتبر enum استفاده میکنیم.
function isInEnum<T>(x: any, enumObj: Record<string, T>): x is T {
return Object.values(enumObj).includes(x);
}
function castToType<T>(x: any, enumObj: Record<string, T>, d: T): T {
return isInEnum(x, enumObj) ? x : d;
}
const v1 = castToType("value1", MyEnum, MyEnum.Value2)
const v3 = castToType("value3", MyEnum, MyEnum.Value2)
لینک محیط بازی Typescript
