آیا در تایپاسکریپت نوعی وجود دارد برای هر چیزی به جز توابع؟
میخواهم بیان کنم که یک پارامتر باید یک شیء یا یک نوع مقدار ساده (عدد، بولی، رشته و غیره) باشد، اما نه یک تابع.
اگر من از Object استفاده کنم، کامپایلر اجازه میدهد که یک تابع را اختصاص دهم.
var test: Object = () => "a";
اگر من از any استفاده کنم، البته همان نتیجه هم خواهد بود. آیا نوع یا ترفندی وجود دارد که بتواند در این مورد به من کمک کند؟
هدف اصلی من تضمین ایمنی هنگام استفاده از مشاهدات Knockout است، تا فراموش نکنم آن پرانتزهای کوچک را برای باز کردن آنها :)
پاسخ شماره ۱
ویژگی جدید پاسخ
افزوده شده در نوامبر ۲۰۱۸ - زیرا اکنون انواع شرطی وجود دارند!
نوعهای شرطی راهحلی ممکن برای این ارائه میدهند، زیرا شما میتوانید یک نوع شرطی NotFunction ایجاد کنید، همانطور که در زیر نشان داده شده است:
type NotFunction<T> = T extends Function ? never : T;
این به این صورت عمل میکند:
const aFunction = (input: string) => input;
const anObject = { data: 'some data' };
const aString = 'data';
// Error function is not a never
const x: NotFunction<typeof aFunction> = aFunction;
// OK
const y: NotFunction<typeof anObject> = anObject;
const z: NotFunction<typeof aString> = aString;
تنها ضعفی که در این وجود دارد این است که شما باید متغیر را در سمت چپ و سمت راست عبارت قرار دهید - اگر اشتباهی مانند زیر مرتکب شوید، با این حال ایمنی وجود دارد:
// Error - function is not a string
const x: NotFunction<typeof aString> = aFunction;
پاسخ اصلی
شما میتوانید یک بررسی زمان اجرا با استفاده از typeof ارائه دهید، که اگرچه بررسی زمان کامپایل نیست، اما مواردی را که فراموش میکنید تابع را اجرا کنید، شناسایی خواهد کرد:
function example(input: any) {
if (typeof input === 'function') {
alert('You passed a function!');
}
}
function someFunction() {
return 1;
}
// Okay
example({ name: 'Zoltán' });
example(1);
example('a string');
example(someFunction());
// Not okay
example(function () {});
example(someFunction);
چرا واقعاً نمیتوانی کاری را که میخواهی انجام بدهی؟
شما تقریباً میتوانید، زیرا میتوانید از اورلودی استفاده کنید تا اجازه دهید «یکی از چند نوع» استفاده شود، برای مثال:
class Example {
someMethod(input: number);
someMethod(input: string);
someMethod(input: boolean);
someMethod(input: any) {
}
}
اینجا مشکل به وجود میآید: برای اینکه اجازهی نوع دادهی شیء داده شود، شما باید یک امضای اضافه بار از someMethod(input: Object); یا someMethod(input: {}); اضافه کنید. به محض اینکه این کار را انجام دهید، توابع نیز مجاز خواهند شد، زیرا تابع از شیء ارثبری میکند.
اگر میتوانستید object را به چیزی کمتر کلی محدود کنید، میتوانستید به سادگی بیش و بیش بارگذاریهای اضافی (وای) برای تمام نوعهایی که میخواهید اجازه دهید اضافه کنید.
پاسخ شماره ۲
شما میتوانید این کار را در TypeScript 2.8 با نوعهای شرطی انجام دهید.
type NotFunc<T> = Exclude<T, Function>
function noFunc <T> (notF: T & NotFunc<T>) { return notF }
const f = () => 2
noFunc(f) // error!
noFunc(f()) // compiles!
اگر سیستم نوع بتواند تصمیم بگیرد که T از Function ارثبری میکند (یعنی T یک تابع است)، آنگاه نوع never خواهد بود، که یک خطای زمان کامپایل است. در غیر این صورت، نوع T خواهد بود و کد شما کامپایل میشود.
با این حال، شما باید این را بخوانید تا بهتر بفهمید چه اتفاقی در حال رخ دادن است:
// type NotFunc<T> = T extends Function ? never : T
type NotFunc<T> = Exclude<T, Function>
// the imporant cases for us are any and {}
type AnyNotFunc = NotFunc<any> // any
type ObjNotFunc = NotFunc<{}> // {}
type NullNotFunc = NotFunc<null> // never
// some functions, explicitly typed and inferred
const f: Function = () => 2
const ff = () => 2
const g: Function = (): null => null
const gg = (): null => null
// so a function like this won't work:
function badNoFunc <T> (notF: NotFunc<T>) { return notF }
// these all compile, because T is inferred as {} and NotFunc<{}> is just {}
badNoFunc(f)
badNoFunc(g)
badNoFunc(ff)
badNoFunc(gg)
// so need the T & NotFunc<T> to give the compiler a hint as to the type of T
function noFunc <T> (notF: T & NotFunc<T>) { return notF }
// now f is correctly inferred to be Function
noFunc(f) // error! f is assignable to Function
noFunc(g) // error! g is assignable to Function
noFunc(f()) // OK! 2 is not assignable to Function
// but we would expect g() === null to be never since NotFunc<null> === never
noFunc(g()) // OK? even though null is assignable to Function?
noFunc<null>(g()) // Error! Ah, type Function represents () => any but NotFunc<null> is never
// if we use the implicitly typed version, gg, the compiler infers the null return value correctly
noFunc(gg()) // Error! Correct
noFunc(ff) // error! The type is correctly inferred to be function
noFunc(gg) // error! The type is correctly inferred to be function
noFunc(ff()) // OK! 2 is not assignable to Function
نکات اصلی:
- نویسنده اصلی میتواند هر کاری که میخواهد انجام دهد
- نوع
Functionبه اندازهanyبد است، پس از آن اجتناب کنید
