برنامه نویسی

تایپ های پیشرفته

بیایید فرض کنیم شما در حال تلاش برای ایجاد یک مؤلفه عمومی هستید که یک عملکرد واگذار کننده داده را دریافت می کند ، اجازه دهید آن را صدا کنیم fn، که یک مورد یا آرایه ای از نوع و یک نوع دیگر را برمی گرداند ، اجازه می دهد تا آن را صدا کنیم key، با یکی از کلیدهای نوع بازگشت عملکرد.

به منظور بدست آوردن خودکار برای key prop
اتمام خودکار

عملکرد داده های داده

async function getData() {
  return {key1: "b", key2: 4, key3: false};
}

سوال

چگونه می توان نوع یک مؤلفه دیگر را برای پذیرش اعلام کرد تنها کلیدهای نوع داده بازگردانده شده توسط تابع داده-فالژ.

روند

شما می توانید “به راحتی” غرفه ها را به شرح زیر تایپ کنید:

type ReturnedType = {
  key1: string
  key2: number
  key3: boolean
}
type ComponentProps = {
  fn: () => Promise<ReturnedType>
  key: "key1" | "key2" | "key3"
}

اما این واقعاً مقیاس نمی شود زیرا مؤلفه عمومی نیست ، به این معنی که عملکرد داده ها فقط می تواند یک شیء باشد که یک شی را با شکل ReturnedType بازگرداند.

همچنین ، هر بار که نوع تغییر یافته تغییر می کند ، باید در نوع آن تغییراتی ایجاد کنیم key prop

یادداشت
ما همچنین می توانیم اعلام کنیم keyنوع prop به عنوان keyof ReturnedTypeبشر

رفع: keyof

به جای تعریف نوع غرفه ها ، نوع و استفاده از مؤلفه خود را تعریف خواهیم کرد keyof برای تعریف نوع key پروپ ، در نتیجه نوع اتحاد کلیدهای پاسخ مورد انتظار عملکردی که ما از آن عبور خواهیم کرد fnبشر

tl ؛ دکتر:

type ComponentType = <
  F extends () => Promise<Record<string, unknown>>, 
  D extends Awaited<ReturnType<F>>
> ({
  fn,
  key
}: {
  fn: F,
  key: keyof D
}) => React.JSX.Element | null

در صورت بازگشت عملکرد یک آرایه:

type ComponentType = <
  F extends () => Promise<Record<string, unknown>>, 
  D extends Awaited<ReturnType<F>>[number]
> ({
  fn,
  key
}: {
  fn: F,
  key: keyof D
}) => React.JSX.Element | null

در این حالت ما باید نوع را بررسی کنیم key به عنوان “رشته” باشید:

// Server component
const Component: ComponentType = async ({fn, key}) => {
  const item = await fn();
  if (typeof key !== "string") return null;
  return <>{item[key]}</>
}
// Client component
const Component: ComponentType = ({fn, key}) => {
  const [item, setItem] = useState();
  useEffect(() => {
    fn().then(setItem)
  }, [])
  if (typeof key !== "string") return null;
  return <>{item[key]}</>
}

راه دیگر برای انجام آن (با عملکردی که یک آرایه را برمی گرداند و با استفاده از یک یاور استنباط):

type KeyOf<T> = T extends Record<infer K extends string, unknown> ? K : never;
async function Component<F extends () => Promise<Record<string, unknown>[]>>(fn: F, key: KeyOf<Awaited<ReturnType<F>>[number]>): React.JSX.Element {
  const item = await fn()
  // there is no need to check for key to be string
  return <>{item[key]}</>;
}

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا