تایپاسکریپت - چگونه نوع بازگشتی برای پارامترهای خاص یک تابع عمومی را بهدست آوریم؟


من میخواهم یک نوع کمکی ایجاد کنم که یک امضای تابع عمومی و آرگومانهای آن را بگیرد. این نوع باید منجر به نوع بازگشتی امضا شود، همانطور که اگر با آرگومانهای ارائهشده اجرا میشد، به دست میآمد.

من این را امتحان کردم:

type GetReturnType<T extends (...args: any) => any, B> = T extends (...args: any) => infer R ? R : never;

اما همه جنریکها در نهایت به unknown یا never تبدیل میشوند.

برخی از توابع مثالی که ممکن است بخواهم ارسال کنم:

function myFn1<T>(x: T) {
    return {
        a: x,
    }
}

function myFn2<T>(x: T) {
    return [x];
}

function myFn3<T>(x: T) {
    if (typeof x == "string") {
        return "yes" as (T extends string ? "yes" : "no");
    } else {
        return "no" as (T extends string ? "yes" : "no");
    }
}

و چطور دوست دارم GetReturnType استفاده شود:

type Return1 = GetReturnType<typeof myFn1, [x: number]>; // expected {a: number}
type Return2 = GetReturnType<typeof myFn2, [x: number]>; // expected number[]
type Return3A = GetReturnType<typeof myFn3, [x: number]>; // expected "no"
type Return3B = GetReturnType<typeof myFn3, [x: string]>; // expected "yes"

لینک زمین بازی

TypeScript از قبل یک سیستم برای استنتاج نوعهای عمومی توابع دارد. برای مثال myFn3("some string") اولین آرگومان عمومی را به عنوان یک رشته استنتاج میکند و در نتیجه مقدار بازگشتی "yes" خواهد بود. من میخواهم از این سیستم هنگام تلاش برای گرفتن نوع بازگشتی استفاده کنم. دیگر سوالها در SO پرسیدهاند چگونه این کار را زمانی انجام دهیم که نوعهای عمومی شناخته شدهاند، اما من میخواهم بدانم چگونه این کار را وقتی نوعهای عمومی استنتاج شدهاند انجام دهیم.

پاسخ شماره ۱

const to = <A>(value: A) => ({ value } as const);

type ApplyTo<A> = ReturnType<typeof to<A>>;

const map = <A extends unknown[]>(value: readonly [...A]) => value.map(to) as {
  [K in keyof A]: ApplyTo<A[K]>;
};


type t2 = ReturnType<typeof map<["a", "b", "c"]>>;
// type t2 = [{
//   readonly value: "a";
// }, {
//   readonly value: "b";
// }, {
//   readonly value: "c";
// }]

فکر میکنم این تا جایی که ممکن است نزدیک است. بهتر بود اگر میتوانستیم to را به عنوان یک پارامتر ارسال کنیم، اما تا جایی که میدانم، این امکانپذیر نیست.

پاسخ شماره ۲

همان سوال، چرا میتوانم ارزش اضافی بازگردانم؟

type RX = { id: number; name: string };
type GetProduct = (name: string) => RX;

const getProduct: GetProduct = (name) => ({ id: 123, name, city: "" });

مثل شهر اینجا