TypeScript - محدود کردن نوع enum به یک عضو واحد
enum Unit {
Kilometer,
Meter,
}
interface Measurement {
distanceUnit: Unit
distance: number
}
interface MetersMeasurement {
distanceUnit: Unit.Meter
}
function someCalculation(item: MetersMeasurement){
return;
}
function main(){
const item : Measurement = {
distance: 100,
distanceUnit: Unit.Meter
}
if(item.distanceUnit !== Unit.Meter) return;
someCalculation(item)
// ^^^^ Types of property 'distanceUnit' are incompatible.
// Type 'Unit' is not assignable to type 'Unit.Meter'.
}
زمین بازی
اگر
MetersMeasurementوMeasurementهمان فیلدها را داشتند، میتوانستیم از یک پراپدیکت نوع برای محدود کردن آن استفاده کنیم. اما مشکل من این است کهMetersMeasurementتنها یک زیرمجموعه از فیلدهایMeasurementرا خواهد داشت. بنابراین یک پراپدیکت نوع کار نخواهد کرد [playground].ما همچنین میتوانیم نوع
distanceUnitدر اینترفیسMetersMeasurementرا بهUnitتغییر دهیم. و سپس بررسیifبرای متر را داخل تابعsomeCalculationمنتقل کنیم. اما فرض کنید من نمیخواهم این کار را انجام دهم. نمیخواهم این مسئولیت را به تابع بدهم.ما میتوانیم یک شیء جدید از نوع
MetersMeasurementبر اساس شیء اصلی ایجاد کنیم و سپس آن را بهsomeCalculation()ارسال کنیم. اما این شبیه یک راهحل موقت (و کد اضافی) به نظر میرسد چون نتوانستیم نوع را محدود کنیم [playground].
آیا راهی وجود دارد که نوع را به درستی محدود کرد بدون اینکه قوانین شکسته شود؟ (بدون any یا تبدیل نوع)
پاسخ شماره ۱
شما میتوانید از یک نگهبان نوع استفاده کنید تا بررسی کنید که آیا مورد MetersMeasurement است یا Measurement
enum Unit {
Kilometer,
Meter,
}
interface Measurement {
distanceUnit: Unit
distance: number
}
interface MetersMeasurement {
distanceUnit: Unit.Meter
}
function someCalculation(item: MetersMeasurement){
return;
}
function isMeasurement(obj: Measurement): obj is Measurement {
return (obj as Measurement).distance !== undefined;
}
function main(){
const item = {
distance: 100,
distanceUnit: Unit.Meter
}
if(isMeasurement(item)) return;
someCalculation(item)
}
پاسخ شماره ۲
این را امتحان کن:
enum Unit {
Kilometer,
Meter,
}
type Distance = {
distance: number;
}
type MetersMeasurement = {
distanceUnit: Unit.Meter;
} & Distance
type KilometersMeasurement = {
distanceUnit: Unit.Kilometer;
} & Distance
type Measurement = MetersMeasurement | KilometersMeasurement;
/*
* return km
*/
function meterCalculation(item: MetersMeasurement) {
return item.distance * .001;
}
function main(){
const item : Measurement = {
distance: 100,
distanceUnit: Unit.Meter
}
if (item.distanceUnit == Unit.Meter) {
meterCalculation(item);
}
}
زمین بازی
