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

بیایید فرض کنیم شما در حال تلاش برای ایجاد یک مؤلفه عمومی هستید که یک عملکرد واگذار کننده داده را دریافت می کند ، اجازه دهید آن را صدا کنیم 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]}</>;
}