Typescript: Standard-Requisiten funktionieren nicht in der Funktionskomponente

Erstellt am 4. Mai 2019  ·  16Kommentare  ·  Quelle: microsoft/TypeScript

TypeScript-Version: 3.4.5

Suchbegriffe:
Reagieren Sie auf die Standard-Requisiten der defaultProps-Funktionskomponente ohne Status

Code

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

Erwartetes Verhalten:
Gemäß den Versionshinweisen zu optional -Stütze in Test nicht erforderlich sein, da sie mit einer Standardeinstellung unter Verwendung der ES2015-Standardinitialisiererfunktion in Component .

Tatsächliches Verhalten:
Der folgende Kompilierungsfehler wird ausgelöst:

Die Eigenschaft 'optional' fehlt im Typ '{name: string; } ', aber erforderlich in Typ' Requisiten '.

Spielplatz Link:
Verknüpfung
Es sieht nicht so aus, als würde der Spielplatz TSX unterstützen.

Verwandte Themen:

27425

Question

Hilfreichster Kommentar

Mit TypeScript 3.1 oder höher sollten Sie schreiben können:

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

Alle 16 Kommentare

Die Dokumentation ist hierzu möglicherweise nicht klar, aber Sie müssen die Eigenschaft in Ihrer Props -Schnittstelle als optional markieren:

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

Das scheint nicht mit den Versionshinweisen übereinzustimmen:

export interface Props {
    name: string;
}

// ...

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

Wenn Sie die Requisite optional machen, bedeutet dies auch, dass das Typsystem beim Zugriff auf die Requisiten außerhalb der Komponente (in einem Test) nicht garantiert, dass die Requisite vorhanden ist, obwohl sie immer vorhanden ist.

Beispiel:

const wrapper = shallow(<Test/>);

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

Wenn optional eine Funktion wäre, müssten Sie überprüfen, ob sie vorhanden ist, bevor Sie sie ausführen. Ein Beispiel ist, wenn Sie eine Standard-Requisite onClick angeben, die nur preventDefault aufruft.

Mit TypeScript 3.1 oder höher sollten Sie schreiben können:

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

Ist es ein Fehler, dass die Verwendung der Standardinitialisierungsfunktion für Standardrequisiten nicht funktioniert? Es scheint eine Regression zu sein, da das in den Versionshinweisen angegebene Beispiel in der neuesten TypeScript-Version nicht funktioniert.

@tbassetto Das Problem dabei ist, dass TS Sie nicht zwingt, tatsächlich einen Standardwert

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

Die andere ärgerliche Sache ist die Tatsache, dass Sie dies zuerst tun müssen: Wenn ich Comp als React.FC<Props> , dann wird defaultProps eingegeben, aber es treten andere Probleme auf .

Alles in allem scheint die Unterstützung für TypeScripts JSX / React im Moment in einem seltsamen, nicht ganz perfekten Zustand zu sein, aber es läuft so, als ob alles in Ordnung wäre (zumindest in meinen Augen - Hauptsächlich kann ich keinen soliden finden Hinweise zur derzeit "offiziellen" Methode zur zustandslosen Reaktion von Komponenten auf typsichere Weise für 3.4.5).

Obwohl ich sehe, dass jeder auf Workarounds verweist, kann ich keinen von ihnen zum Arbeiten bringen.

Ich bin auf Version 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;

Hat jemand einen Einblick, warum dies immer noch den Fehler auslöst

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

Ich habe auch alle in # 27425 und # 519 vorgeschlagenen Korrekturen ausprobiert.

@tomspeak Entweder meine Problemumgehung oder die @Hotell (obwohl hier alle Requisiten optional sind). Getestet auf 3.5 mit Ihrem Beispielcode.

Obwohl ich sehe, dass jeder auf Workarounds verweist, kann ich keinen von ihnen zum Arbeiten bringen.

Ich bin auf Version 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;

Hat jemand einen Einblick, warum dies immer noch den Fehler auslöst

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

Ich habe auch alle in # 27425 und # 519 vorgeschlagenen Korrekturen ausprobiert.

Sie müssen nur shouldTruncateContent erstellen: boolean; optional shouldTruncateContent?: boolean;

Die Dokumentation ist hierzu möglicherweise nicht klar, aber Sie müssen die Eigenschaft in Ihrer Props -Schnittstelle als optional markieren:

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

Ich benutze diesen optionalen Typ überall. Warum die Abwahl? Könnte jemand erklären?

@ralexhassle , ich kann die Abstimmungen nicht erklären, aber ich kann erklären, dass dies sicherlich eine korrekte Art ist, die optionale Eigenschaft einer Komponente einzugeben.
Vielleicht bevorzugen Sie die Verwendung von defaultProps , die im Beispiel der Frage nicht verwendet wird, aber für mich ist es wahrscheinlich vollkommen in Ordnung, optionale Eigenschaften als optional zu markieren ...

Der Zweck des Problems besteht darin, dass die Requisiten nicht optional sind, sondern einen Standardwert haben (kann daher bei Verwendung der Komponente vermieden werden). Wenn Sie die Requisite optional mit ? markieren, geht TS davon aus, dass sie undefiniert sein könnte, und zwingt Sie, diesen Fall zu behandeln. Es wird jedoch niemals undefiniert sein, da es einen Standardwert gibt. Die Abstimmungen sind darauf zurückzuführen, dass der Kommentator das Problem nicht zu verstehen schien und etwas vorschlug, das den Versionshinweisen zu 3.0 widersprach.

@ RyanCavanaugh, warum hat der Bot dieses Problem geschlossen?

Vielleicht habe ich es verpasst, aber ich sehe trotz vieler Problemumgehungen keine tatsächliche Antwort?

PS: mit TypeScript v4

Sie können dies auf diese Weise tun. Hier sind Eigenschaften in Requisiten der optionale Parameter und werden in der Komponente weiter verwendet.

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 Mit dieser Ausgabe soll

Ich konnte keine Standardargumente für die Funktion oder andere Vorschläge für die ordnungsgemäße Typprüfung abrufen. Die einzige praktikable Lösung, die ich finden konnte, ist folgende:

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

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen