typescript - گارد نوع برای فیلدهای اینترفیس در شاخه else
interface Test<T> {
field: string | T;
}
function isString<T>(test: Test<T>): test is Test<string> {
return typeof test.field === "string";
}
function f<T>(test: Test<T>) {
if (isString(test)) {
const a = test.field; // the type of a is string
} else {
const b = test.field; // the type of b is string | T
}
}
در کد بالا، در شاخه if، a از نوع string است، که درست است. با این حال، در شاخه else، b از نوع string | T است.
حتی اگر یک بررسی برای T اضافه کنم، همان نتیجه را میگیرم:
function isT<T>(test: Test<T>): test is Test<T> {
return typeof test.field !== "string";
}
function f<T>(test: Test<T>) {
if (isString(test)) {
const a = test.field; // the type of a is string
} else if (isT(test)) {
const b = test.field; // the type of b is string | T
}
}
چه کاری میتوانم انجام دهم تا b را صریحاً به T تبدیل نکنم، درست همانطور که نیازی به تبدیل a به string ندارم؟
پاسخ شماره ۱
مشکل این است که محافظ نوع تعریفشده توسط کاربر نوع Test<T> را بررسی میکند، اما آنچه شما میخواهید نوع field است.
شما شاخهبندی خود را اینگونه دارید:
function f<T>(test: Test<T>) {
if (isString(test)) {
// We have a `Test<string>`
const a = test.field;
} else {
// We do not have a `Test<string>`
const b = test.field;
}
}
در شاخه if، ما یک Test<string> داریم، و ویژگی field آن یک اتحاد از string | string است (که فقط یک string است). نوع آن به این شکل است:
interface Test<string> {
field: string | string;
}
در شاخه else، ما یک Test<SomeNonString> داریم و ویژگی field آن ترکیبی از string | SomeNonString است. نوع آن به این شکل به نظر میرسد:
interface Test<SomeNonString> {
field: string | SomeNonString;
}
در آن شاخهی else، ما نیاز به رفع ابهام داریم، زیرا field هنوز یک نوع اتحادی است. تا زمانی که رابط Test<T> field را به عنوان یک نوع اتحادی از string | T تعریف کند، ما به آزمون بعدی نیاز خواهیم داشت هر زمان که T برابر با string نباشد.
در اینجا یک نمونه است:
function isFieldString<T>(field: string | T): field is string {
return typeof field === "string";
}
function f<T>(test: Test<T>) {
if (isString(test)) {
const s = test.field; // const s: string
} else if (isFieldString(test.field)) {
const s = test.field; // const s: string
} else {
const t = test.field; // const t: T
}
}
