Typescript: 機能コンポーネントで機能しないデフォルトの小道具

作成日 2019年05月04日  ·  16コメント  ·  ソース: microsoft/TypeScript

TypeScriptバージョン: 3.4.5

検索ワード:
デフォルトの小道具に反応するdefaultProps機能コンポーネントステートレス

コード

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

予想される行動:
TypeScript 3.0リリースノートによると、 optional小道具はComponentのES2015デフォルト初期化機能を使用してデフォルトで定義されているため、 Testでは必要ありません。

実際の動作:
次のコンパイルエラーがスローされます。

プロパティ 'optional'がタイプ '{name:string;にありません。 } 'ですが、タイプ'小道具 'では必須です。

遊び場リンク:
リンク
遊び場がTSXをサポートしているようには見えません。

関連する問題:

27425

Question

最も参考になるコメント

TypeScript 3.1以降では、次のように記述できるはずです。

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

全てのコメント16件

ドキュメントはこれについて明確ではないかもしれませんが、 Propsインターフェースでプロパティをオプションとしてマークする必要があります。

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

これは、リリースノートの内容と一致していないようです。

export interface Props {
    name: string;
}

// ...

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

小道具をオプションにするということは、コンポーネントの外部で(テストで)小道具にアクセスするときに、型システムは、小道具が常に存在する場合でも、その存在を保証しないことも意味します。

例:

const wrapper = shallow(<Test/>);

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

optionalが関数の場合、実行する前に関数が存在することを確認する必要があります。 例として、 preventDefault呼び出すだけのデフォルトのonClick小道具を提供する場合があります。

TypeScript 3.1以降では、次のように記述できるはずです。

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

デフォルトの初期化機能の使用がデフォルトの小道具で機能しないのはバグですか? リリースノートに記載されている例が最新のTypeScriptバージョンでは機能しないことを考えると、リグレッションのように見えます。

@tbassettoそれに関する問題は、TSが実際にデフォルト値を提供することを強制しないことです。

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

もう1つの厄介な点は、最初にこれを実行する必要があるという事実です。 CompReact.FC<Props>と入力すると、 defaultPropsは適切に入力されますが、他の問題が発生します。 。

全体として、TypeScripts JSX / Reactのサポートは現在、奇妙な「完全ではない」状態にあるように見えますが、すべてが正常であるかのように実行されています(少なくとも私の目には-主に、私は固体を見つけることができないようです3.4.5のタイプセーフな方法でステートレスReactコンポーネントを実行するための現在の「公式」方法についてのメモ。

誰もが回避策を参照しているのを目にしますが、それらのいずれも機能させることができません。

私はバージョン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;

なぜこれがまだエラーをスローするのかについて誰かが洞察を持っていますか

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

#27425と#519で提案されたすべての修正も試しました。

@tomspeakどちらか私の回避策または@Hotellworaround (この1つは、すべての小道具はオプションになりますが)。 サンプルコードを使用して3.5でテストしました。

誰もが回避策を参照しているのを目にしますが、それらのいずれも機能させることができません。

私はバージョン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;

なぜこれがまだエラーをスローするのかについて誰かが洞察を持っていますか

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

#27425と#519で提案されたすべての修正も試しました。

shouldTruncateContent:boolean;を作成する必要があります。 オプションのshouldTruncateContent?: boolean;

ドキュメントはこれについて明確ではないかもしれませんが、 Propsインターフェースでプロパティをオプションとしてマークする必要があります。

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

私はどこでもこのオプションのタイプを使用しています。 なぜ反対票を投じるのですか? 誰かが説明できますか?

@ralexhassle
質問の例では使用されていないdefaultPropsを使用することをお勧めしますが、私に関する限り、オプションのプロパティをオプションとしてマークすることはおそらく完全に問題ありません...

この問題の目的は、小道具がオプションではなく、デフォルト値を持っていることです(したがって、コンポーネントを使用するときに回避できます)。 小道具を?オプションとしてマークすると、TSはそれが未定義である可能性があると見なし、その場合の処理​​を強制します。 ただし、デフォルト値があるため、未定義になることはありません。 反対票は、コメンテーターが問題を理解していないようで、3.0リリースノートと矛盾する何かを提案したためです。

@RyanCavanaughボットがこの問題を

おそらく私はそれを見逃しましたが、多くの回避策にもかかわらず、実際の答えが表示されませんか?

PS:TypeScriptv4を使用

この方法でそれを行うことができます。ここでは、小道具のプロパティはオプションのパラメータであり、コンポーネントでさらに使用されます。

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この問題の目的は、小道具タイプをオプションとしてマークしないようにすることです。

関数のデフォルト引数やその他の型チェックを正しく行うための提案を取得できませんでした。 私が見つけた唯一の実行可能な解決策はこれです:

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

このページは役に立ちましたか?
0 / 5 - 0 評価