Versão TypeScript: 3.4.5
Termos de pesquisa:
react default props defaultProps componente funcional stateless
Código
import React from "react";
interface Props {
name: string;
optional: string;
}
const Component = ({ name, optional = "default" }: Props) => (
<p>{name + " " + optional}</p>
);
const Test = () => <Component name="test" />;
Comportamento esperado:
De acordo com as notas de lançamento do optional
prop não deve ser exigido em Test
, pois foi definido com um padrão usando o recurso de inicializadores padrão ES2015 em Component
.
Comportamento real:
O seguinte erro de compilação é gerado:
Propriedade 'opcional' ausente no tipo '{nome: string; } 'mas necessário no tipo' Props '.
Link Playground:
Ligação
Não parece que o playground suporta TSX.
Assuntos relacionados:
A documentação pode não ser clara sobre isso, mas você deve marcar a propriedade como opcional em sua interface Props
:
interface Props {
name: string;
optional?: string;
}
Isso não parece corresponder ao que dizem as notas de lançamento:
export interface Props {
name: string;
}
// ...
function Greet({ name = "world" }: Props) {
return <div>Hello {name.toUpperCase()}!</div>;
}
Tornar o adereço opcional também significa que, quando você acessa os adereços fora do componente (em um teste), o sistema de tipos não garante que o adereço exista, embora sempre existirá.
Exemplo:
const wrapper = shallow(<Test/>);
// optional is string | undefined instead of string
const optional = wrapper
.find(Component)
.props()
.optional;
Se optional
fosse uma função, você teria que verificar se ela existe antes de executá-la. Um exemplo é se você fornecer um onClick
prop padrão que apenas chama preventDefault
.
Com TypeScript 3.1 ou superior, você deve ser capaz de escrever:
export interface Props {
name: string;
}
function Greet(props: Props) {
return <div>Hello {props.name.toUpperCase()}!</div>;
}
Greet.defaultProps = {
name: "world",
} as Partial<Props>; // Good practice, without it you could use a number as default prop and TypeScript wouldn't complain…
const component = <Greet />; // no errors
É um bug que usar o recurso inicializador padrão não funciona para adereços padrão? Parece uma regressão, visto que o exemplo fornecido nas notas de lançamento não funciona na última versão do TypeScript.
@tbassetto O problema com isso é que o TS não força você a fornecer um valor padrão:
import React from 'react';
interface Props {
myProp: string;
}
const Comp = (props: Props) => {
return (
<div>
{props.myProp.toUpperCase()}
</div>
);
};
Comp.defaultProps = {
} as Pick<Props, 'myProp'>;
const comp = <Comp />;
A outra coisa irritante é o fato de você ter que fazer isso em primeiro lugar: se eu digitar Comp
como React.FC<Props>
, então defaultProps
está bem digitado, mas outros problemas surgem .
Em suma, o suporte de TypeScripts JSX / React agora parece estar em um estado estranho "não muito perfeito", mas funcionando como se tudo estivesse bem (pelo menos aos meus olhos - principalmente, não consigo encontrar nenhum sólido notas sobre o que atualmente é a maneira "oficial" de fazer componentes sem estado do React de uma maneira segura para o tipo 3.4.5).
Embora eu veja todos fazendo referência a work arounds, não consigo fazer nenhum deles funcionar.
Estou na versão 3.3.3
export interface Props {
shouldTruncateContent: boolean;
}
const Alert: React.FunctionComponent<Props> = ({
children,
shouldTruncateContent = false
}) => {
return (
<S.Content shouldTruncateContent={shouldTruncateContent} size="fill">
{children}
</S.Content>
);
};
Alert.defaultProps = {
shouldTruncateContent: false
} as Pick<Props, 'shouldTruncateContent'>;
export default Alert;
Alguém tem alguma ideia de por que isso ainda gera o erro
TS2741: Property 'shouldTruncateContent' is missing in type '{ children: string; }' but required in type 'Props'.
Eu tentei todas as correções propostas em # 27425 e # 519 também.
@tomspeak Ou minha solução alternativa ou 's @Hotell woraround (embora este faz todos os adereços opcional). Testado em 3.5 com seu código de amostra.
Embora eu veja todos fazendo referência a work arounds, não consigo fazer nenhum deles funcionar.
Estou na versão 3.3.3
export interface Props { shouldTruncateContent: boolean; } const Alert: React.FunctionComponent<Props> = ({ children, shouldTruncateContent = false }) => { return ( <S.Content shouldTruncateContent={shouldTruncateContent} size="fill"> {children} </S.Content> ); }; Alert.defaultProps = { shouldTruncateContent: false } as Pick<Props, 'shouldTruncateContent'>; export default Alert;
Alguém tem alguma ideia de por que isso ainda gera o erro
TS2741: Property 'shouldTruncateContent' is missing in type '{ children: string; }' but required in type 'Props'.
Eu tentei todas as correções propostas em # 27425 e # 519 também.
Você só precisa fazer shouldTruncateContent: boolean; opcional shouldTruncateContent?: boolean;
A documentação pode não ser clara sobre isso, mas você deve marcar a propriedade como opcional em sua interface
Props
:interface Props { name: string; optional?: string; }
Estou usando esse tipo opcional em todos os lugares. Por que o voto negativo? Alguém poderia explicar?
@ralexhassle , não posso explicar os votos negativos, mas posso explicar que é certamente uma forma correta de digitar a propriedade opcional de um componente.
Você pode preferir usar defaultProps
, que o exemplo da pergunta não está usando, mas, no que me diz respeito, marcar propriedades opcionais como opcionais é provavelmente perfeitamente adequado ...
O objetivo do problema é que os adereços não são opcionais, mas têm um valor padrão (portanto, podem ser iludidos ao usar o componente). Se você marcar o prop opcional com ?
, o TS assume que ele pode ser indefinido e força você a lidar com esse caso. No entanto, ele nunca será indefinido porque há um valor padrão. Os votos negativos são porque o comentarista não pareceu entender o problema e propôs algo que contradiz as notas de lançamento do 3.0.
@RyanCavanaugh por que o bot fechou esse problema?
Talvez eu tenha perdido, mas não vejo uma resposta real, apesar de muitas soluções alternativas.
PS: usando TypeScript v4
Você pode fazer isso desta forma, aqui as propriedades em Props são o parâmetro opcional e posteriormente usado no componente.
interface Props {
children: ReactNode;
properties?: Record<string, unknown>;
}
const defaultProps: Props = {
children: '',
properties: {
marginTop: 32,
marginLeft: 0,
marginBottom: 8,
marginRight: 0,
},
};
const RadioListLabel: React.FC<Props> = ({
children,
properties = defaultProps.properties,
}) => (
<View
margin={[
properties ? properties.marginTop : 0
properties ? properties.marginLeft : 0
properties ? properties.marginBottom : 0
properties ? properties.marginRight : 0
]}
>
<Text size="m" variant="heading2" lineHeight="body">
{children}
</Text>
</View>
)
@lakhmeranikita O objetivo desta edição é evitar marcar um tipo de suporte como opcional.
Não consegui obter argumentos padrão de função ou outras propostas para digitar a verificação corretamente. A única solução viável que consegui encontrar é esta:
import React from "react";
type DefaultProps = { optionalProp: number };
type Props = {
requiredProp: "some_string" | "other_string";
} & DefaultProps;
export const BaseComponent = (props: Props) => {
const { requiredProp, optionalProp } = props;
return (
<div>
{requiredProp} {optionalProp}
</div>
);
};
BaseComponent.defaultProps = {
optionalProp: 0,
} as Partial<DefaultProps>;
const comp = <BaseComponent requiredProp="some_string" />;
Comentários muito úteis
Com TypeScript 3.1 ou superior, você deve ser capaz de escrever: