reactjs - Hur lägger man till defaultProps till en generell funktionell komponent med komponentinjektion i TypeScript?
Jag har en funktionell komponent Button som tar en prop as för att injicera ett HTML-element eller en annan komponent. Jag vill att standardvärdet för as-propen ska vara Link-komponenten från react-router. Detta skulle göra Link-ens to-prop till en obligatorisk prop för Button. Så jag borde få ett fel när jag skriver <Button>Press me!</Button>, men kompilatorn rapporterar inget fel.
Jag använder TypeScript v3.5.3 med följande inställningar i tsconfig.json:
{
"compilerOptions": {
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"alwaysStrict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
Här är min nuvarande situation (förenklad) med Link som standard för as es6-stil:
import React from 'react'
import { Link } from 'react-router-dom'
interface ButtonProps {
children?: string
}
type ElementInjector<T extends React.ElementType> = {
as: T
} & React.ComponentPropsWithoutRef<T>
export const Button = <T extends React.ElementType>({
as: Tag = Link,
...props
}: ButtonProps & ElementInjector<T>) => {
return <Tag {...props} />
}
Så med tanke på ovanstående är detta resultatet och förväntningarna:
<Button>Button</Button> // error - asking for `as` not `to`
<Button as={Link}>Button</Button> // error - ok
<Button to="/">Button</Button> // error - asking for `as`
<Button as="a">Button</Button> // success - ok
Hur får jag den första att misslyckas?
Det skulle också vara coolt att lösa följande också. Inte relaterat till defaultProps utan till det generiska tillvägagångssättet.
<Button as="a" to="/">Button</Button> // success - error expected
<Button<'a'> as="a" to="/">Button</Button> // error - ok
Exempel att leka med
Svar #1
Parameterns standardvärde kommer inte att tas i beaktande när typparametrarna till komponenten härleds. Eftersom det inte finns någon annan plats att ta T ifrån kommer det att standardiseras till unknown. Lösningen skulle vara att lägga till en standardtyp för T
export const Button = <T extends React.ElementType = typeof Link>({
tag: Tag = Link,
...props
}: ButtonProps & ElementInjector<T>) => {
return <Tag {...props} />
}
let x = <Button>Button</Button> // error expected
let x1 = <Button tag={Link}>Button</Button> // error - ok
let x2 = <Button to="/">Button</Button> // success - ok
let x3 = <Button tag="a">Button</Button> // success - ok
Om ditt andra problem, det är liknande den här frågan men jag har inte kunnat få det att fungera, kommer att posta om jag har en uppdatering.
