Typescript: Los accesorios predeterminados no funcionan en el componente funcional

Creado en 4 may. 2019  ·  16Comentarios  ·  Fuente: microsoft/TypeScript

Versión de TypeScript: 3.4.5

Términos de búsqueda:
reaccionar default props defaultProps componente funcional sin estado

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" />;

Comportamiento esperado:
De acuerdo con las notas de la versión de TypeScript 3.0 , el optional prop no debería ser requerido en Test ya que se ha definido con un valor predeterminado utilizando la función de inicializadores predeterminados de ES2015 en Component .

Comportamiento real:
Se produce el siguiente error de compilación:

Falta la propiedad 'opcional' en el tipo '{nombre: cadena; } 'pero es obligatorio en el tipo' Props '.

Enlace de patio de recreo:
Enlace
No parece que el patio de recreo sea compatible con TSX.

Asuntos relacionados:

27425

Question

Comentario más útil

Con TypeScript 3.1 o superior , debería poder escribir:

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

Todos 16 comentarios

Es posible que la documentación no sea clara al respecto, pero debe marcar la propiedad como opcional en su interfaz Props :

interface Props {
    name: string;
    optional?: string;
}

Eso no parece coincidir con lo que dicen las notas de la versión:

export interface Props {
    name: string;
}

// ...

function Greet({ name = "world" }: Props) {
    return <div>Hello {name.toUpperCase()}!</div>;
}

Hacer que el accesorio sea opcional también significa que cuando accedes a los accesorios fuera del componente (en una prueba), el sistema de tipos no garantiza que el accesorio exista aunque siempre existirá.

Ejemplo:

const wrapper = shallow(<Test/>);

// optional is string | undefined instead of string
const optional = wrapper
        .find(Component)
        .props()
        .optional;

Si optional fuera una función, tendría que comprobar que existe antes de ejecutarla. Un ejemplo es si proporciona un onClick prop predeterminado que solo llama a preventDefault .

Con TypeScript 3.1 o superior , debería poder escribir:

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

¿Es un error que el uso de la función de inicializador predeterminada no funcione para los accesorios predeterminados? Parece una regresión dado que el ejemplo dado en las notas de la versión no funciona en la última versión de TypeScript.

@tbassetto El problema con eso es que TS no te obliga a proporcionar un valor predeterminado:

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 />;

La otra cosa molesta es el hecho de que tienes que hacer esto en primer lugar: si escribo Comp como React.FC<Props> , entonces defaultProps está bien escrito, pero surgen otros problemas .

Con todo, el soporte TypeScripts JSX / React en este momento parece estar en un estado extraño, no del todo perfecto, pero funcionando como si todo estuviera bien (al menos en mi opinión, principalmente, parece que no puedo encontrar ningún sólido notas sobre lo que actualmente es la forma "oficial" de hacer componentes React sin estado de forma segura para 3.4.5).

Aunque veo que todos hacen referencia a soluciones alternativas, no puedo hacer que ninguna funcione.

Estoy en la versión 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;

¿Alguien tiene alguna idea de por qué esto todavía arroja el error?

TS2741: Property 'shouldTruncateContent' is missing in type '{ children: string; }' but required in type 'Props'.

También probé todas las correcciones propuestas en # 27425 y # 519.

@tomspeak Cualquiera de mi solución o @Hotell 's woraround (aunque éste hace que todos los apoyos opcional). Probado en 3.5 con su código de muestra.

Aunque veo que todos hacen referencia a soluciones alternativas, no puedo hacer que ninguna funcione.

Estoy en la versión 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;

¿Alguien tiene alguna idea de por qué esto todavía arroja el error?

TS2741: Property 'shouldTruncateContent' is missing in type '{ children: string; }' but required in type 'Props'.

También probé todas las correcciones propuestas en # 27425 y # 519.

Solo necesitas hacer shouldTruncateContent: boolean; opcional shouldTruncateContent?: boolean;

Es posible que la documentación no sea clara al respecto, pero debe marcar la propiedad como opcional en su interfaz Props :

interface Props {
    name: string;
    optional?: string;
}

Estoy usando este tipo opcional en todas partes. ¿Por qué el voto negativo? ¿Alguien podría explicarlo?

@ralexhassle , no puedo explicar los votos
Es posible que prefiera usar defaultProps , que el ejemplo de la pregunta no usa, pero en lo que a mí respecta, marcar propiedades opcionales como opcionales probablemente esté perfectamente bien ...

El propósito del problema es que los accesorios no son opcionales, sino que tienen un valor predeterminado (por lo tanto, se pueden eludir al usar el componente). Si marca el accesorio como opcional con ? , TS asume que podría no estar definido y le obliga a manejar ese caso. Sin embargo, nunca estará indefinido porque hay un valor predeterminado. Los votos negativos se deben a que el comentarista no pareció entender el problema y propuso algo que contradecía las notas de la versión 3.0.

@RyanCavanaugh ¿

¿Quizás me lo perdí pero no veo una respuesta real, a pesar de muchas soluciones?

PD: usando TypeScript v4

Puede hacerlo de esta manera, aquí las propiedades en Props son el parámetro opcional y se usan más en el 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 El propósito de este número es evitar marcar un tipo de accesorio como opcional.

No pude obtener argumentos predeterminados de la función u otras propuestas para escribir check correctamente. La única solución viable que pude encontrar es 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" />;

¿Fue útil esta página
0 / 5 - 0 calificaciones