javascript - Hur annoterar jag React.forwardRef med jsdoc-kommentarer så att intellisense kan visas för den underliggande komponenten?
Jag har en React-komponent skriven som en funktion på detta sätt:
function Button({ text, icon }) {
return ...
}
Button.propTypes = {
text: PropTypes.string.isRequired,
icon: PropTypes.string.isRequired
}
när jag använder denna komponent får jag autokomplettering/intellisense i vscode
Om jag omsluter denna komponent i React.forwardRef, export default React.forwardRef((props, ref) => <Button btnRef={ref} {...props} />)
då får jag intellisense för forwardRef-funktionen, vilket inte hjälper mitt användande, eftersom det nu inte finns något sätt för mig att få propsen autokompletterade/att visas i intellisense.
Jag har försökt annotera React.forwardRef med jsdoc extends/augments men utan framgång, i det fallet slutar till och med standardintellisense för forwardRef-användning att visas. (Jag tror att detta beror på att vscode ger mer företräde till tillgängliga typer än jsdoc-kommentarer). Finns det ett sätt för mig att få intellisense för den omslutna komponenten att fungera på samma sätt som den oomsutna komponenten? Detta skulle stämma överens med min förståelse av att använda den omslutna komponenten på ett liknande sätt som den oomsutna komponenten.
Svar #1
Det beror på hur pedantisk du vill vara när det gäller typerna. Generellt är användningen av dessa komponenter ungefär densamma som andra funktionella komponenter, så det enklaste sättet är att helt enkelt deklarera typen av resultatet som en funktionell komponent. Tricket för props är att först skapa en variabel för prop-typerna och referera till den för generisk typ (eller åtminstone har jag inte hittat ett sätt att få det att fungera utan det mellanliggande värdet):
/**
* @type React.FC<ButtonPropTypes>
*/
const Button = forwardRef(({ text, icon }, ref) => (
<button ref={ref}>{text}{icon}</button>
))
const ButtonPropTypes = {
text: string.isRequired,
icon: string.isRequired,
// `ref` isn't a "real" prop, so `prop-types` will not not actually validate
// this one, but this adds it to the intellisense list if desired. Feel
// free to just omit it.
ref: oneOf(shape({ current: any }), func),
}
Button.propTypes = ButtonPropTypes
Om du vill vara mer exakt, är returtypen av forwardRef faktiskt:
/**
* @type React.ForwardRefRenderFunction<HTMLButtonElement, ButtonPropTypes>
*/
const Button = forwardRef(({ text, icon }, ref) => (
<button ref={ref}>{text}{icon}</button>
))
const ButtonPropTypes = {
text: string.isRequired,
icon: string.isRequired,
}
Button.propTypes = ButtonPropTypes
Dock verkar IntelliSense inte känna igen ref-prop (fungerar bra, bara att den inte finns i listan).
Definitionen för typen finns här: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3423b4fc3e3da09f8acc386bc2fee6fb8f5e0880/types/react/index.d.ts#L559 Den första parametern är den förväntade typen för värdet som kommer att tilldelas ref. Men eftersom du egentligen inte statiskt typifierar ref som du ändå skulle skicka in, kan du helt enkelt välja att utelämna den med en ?:
/**
* @type React.ForwardRefRenderFunction<?, ButtonPropTypes>
*/
Jag tror att det du menar om den sista delen är att du inte skulle ha både den oinslagna och den inslagna versionen. Det är det typiska mönstret, eftersom det egentligen inte finns någon anledning att behålla båda. Men som en parentes kan du direkt hänvisa till propTypes-värdet för vilken annan komponent som helst för användning som en generisk typ, till exempel:
/**
* @type React.FC<UnWrappedButton.propTypes>
*/
