Saya membuat <If />
komponen fungsi sederhana menggunakan React:
import React, { ReactElement } from "react";
interface Props {
condition: boolean;
comment?: any;
}
export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
if (props.condition) {
return <>{props.children}</>;
}
return null;
}
Ini memungkinkan saya menulis kode pembersih, seperti:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
Dalam kebanyakan kasus, ini berfungsi dengan baik, tetapi ketika saya ingin memeriksa misalnya jika variabel yang diberikan tidak didefinisikan dan kemudian meneruskannya sebagai properti, itu menjadi masalah. Saya akan memberi contoh:
Katakanlah saya memiliki komponen bernama <Animal />
yang memiliki Alat Peraga berikut:
interface AnimalProps {
animal: Animal;
}
dan sekarang saya memiliki komponen lain yang membuat DOM berikut:
const animal: Animal | undefined = ...;
return (
<If condition={animal !== undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
);
Seperti yang saya komentari, walaupun sebenarnya hewan tidak didefinisikan, saya tidak punya cara untuk mengatakan bahwa saya sudah memeriksanya. Pernyataan animal!
akan berhasil, tapi bukan itu yang saya cari.
Ada ide?
javascript
reactjs
typescript
Eliya Cohen
sumber
sumber
{animal !== undefined && <Anibal animal={animal} />}
akan berhasil<Animal animal={animal as Animal} />
Jawaban:
Sepertinya tidak mungkin.
Alasan: jika kami mengubah konten
If
komponen darisebaliknya
Anda akan menemukan bahwa kali ini Anda ingin jenis diff diproses dengan cara yang berlawanan.
Yang berarti itu tidak independen, mengarah pada kesimpulan bahwa tidak mungkin untuk membuat tipe seperti itu berbeda dalam kondisi ini, tanpa menyentuh salah satu dari dua komponen.
Saya tidak yakin apa pendekatan terbaik, tapi ini salah satu pemikiran saya.
Anda dapat mendefinisikan
Animal component
alat peragaanimal
dengantipe kondisional distributif naskah : NonNullable .
Dokumen
Pemakaian
Itu tidak dihasilkan oleh kondisi
If
komponen, tetapi karena Anda hanya menggunakan bagianchild component
dalam kondisi itu, masuk akal untuk merancangchild component
alat peraga sebagainone nullable
, dengan syarat bahwasumber
Jawaban singkat?
Kamu tidak bisa
Karena Anda telah menetapkan
animal
sebagaiAnimal | undefined
, satu-satunya cara untuk menghapusundefined
adalah membuat penjaga atau menyusun kembalianimal
sebagai sesuatu yang lain. Anda telah menyembunyikan penjaga tipe di properti kondisi Anda, dan TypeScript tidak memiliki cara untuk mengetahui apa yang terjadi di sana, sehingga tidak dapat mengetahui Anda memilih di antaraAnimal
danundefined
. Anda harus menggunakan atau menggunakannya!
.Pertimbangkan, meskipun: ini mungkin terasa lebih bersih, tetapi itu menciptakan sepotong kode yang perlu dipahami dan dipelihara, mungkin oleh orang lain di ujung tanduk. Intinya Anda membuat bahasa baru, terbuat dari komponen Bereaksi, yang perlu dipelajari seseorang selain TypeScript.
Metode alternatif untuk menghasilkan JSX secara kondisional adalah dengan mendefinisikan variabel
render
yang berisi konten bersyarat Anda, sepertiIni adalah pendekatan standar yang pengembang lain akan langsung mengenali dan tidak perlu melihat ke atas.
sumber
Dengan menggunakan panggilan balik render, saya dapat mengetik bahwa parameter pengembalian tidak dapat dibatalkan.
Saya tidak dapat mengubah
If
komponen asli Anda karena saya tidak tahu apa yang Andacondition
tegaskan dan juga variabel apa yang dinyatakannyacondition={animal !== undefined || true}
Sayangnya, saya membuat komponen baru
IsDefined
untuk menangani kasus ini:Menunjukkan bahwa
children
akan menjadi callback, yang akan melewati NonNullable dari tipe T yang merupakan tipe yang samacheck
.Dengan ini, kita akan mendapatkan panggilan balik render, yang akan melewati variabel nol-diperiksa.
Saya punya contoh yang berfungsi di sini https://codesandbox.io/s/blazing-pine-2t4sm
sumber
If
komponen (sehingga bisa terlihat bersih)