189

Typescript を使用してコンポーネントのデフォルト プロパティ値を設定する方法がわかりません。

これはソースコードです:

class PageState
{
}

export class PageProps
{
    foo: string = "bar";
}

export class PageComponent extends React.Component<PageProps, PageState>
{
    public render(): JSX.Element
    {
        return (
            <span>Hello, world</span>
        );
    }
}

そして、次のようにコンポーネントを使用しようとすると:

ReactDOM.render(<PageComponent />, document.getElementById("page"));

fooプロパティが見つからないというエラーが表示されます。デフォルト値を使用したい。static defaultProps = ...コンポーネント内でも使用しようとしましたが、思ったほど効果がありませんでした。

src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.

デフォルトのプロパティ値を使用するにはどうすればよいですか? 私の会社で使用している多くの JS コンポーネントはそれらに依存しており、それらを使用しないという選択肢はありません。

4

10 に答える 10

390

クラスコンポーネントを使用したデフォルトの小道具

使い方static defaultPropsは正しいです。また、小道具と状態には、クラスではなくインターフェイスを使用する必要があります。

更新 2018/12/1 : TypeScript は、時間の経過とともに関連する型チェックを改善しdefaultPropsました。古い使用法や問題に至るまで、最新かつ最大の使用法について読んでください。

TypeScript 3.0 以降の場合

TypeScriptは、期待どおりに型チェックを機能させるために、特に のサポートを追加しました。defaultProps例:

interface PageProps {
  foo: string;
  bar: string;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, { this.props.foo.toUpperCase() }</span>
        );
    }
}

属性を渡さずにレンダリングおよびコンパイルできるfooもの:

<PageComponent bar={ "hello" } />

ご了承ください:

  • fooJSX 属性として必須ではありませんが、オプション (つまり ) とマークされていません。foo?: stringオプションとしてマークすることは、それが可能であることを意味しますundefinedが、実際にはデフォルト値を提供するundefinedため、決してそうではありません。defaultProps関数パラメーターをオプションまたはデフォルト値でマークする方法と同様に考えてください。ただし、両方ではありませんが、どちらも呼び出しで値を指定する必要がないことを意味します。TypeScript 3.0+defaultPropsも同様の方法で処理します。これは、React ユーザーにとって非常にクールです!
  • にはdefaultProps明示的な型注釈はありません。その型はコンパイラによって推測され、どの JSX 属性が必要かを判断するために使用されます。のサブセットと一致するdefaultProps: Pick<PageProps, "foo">ことを確認するために使用できます。この警告の詳細については、こちらで説明していますdefaultPropsPageProps
  • これには@types/reactバージョン16.4.11が正しく機能する必要があります。

TypeScript 2.1 から 3.0 まで

TypeScript 3.0 がコンパイラ サポートを実装する前defaultPropsは、まだそれを利用でき、実行時に React で 100% 動作しましたが、TypeScript は JSX 属性をチェックするときに props のみを考慮したため、デフォルトを持つ props を でオプションとしてマークする必要があり?ます。例:

interface PageProps {
    foo?: string;
    bar: number;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps: Partial<PageProps> = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, world</span>
        );
    }
}

ご了承ください:

  • props に対して型チェックを行うように で注釈を付けるのは良い考えdefaultPropsですが、すべての必須プロパティにデフォルト値を指定する必要はありません。必須プロパティはデフォルトを必要としないため、意味がありません。Partial<>
  • strictNullChecksの値を使用する場合は、 null 以外のアサーション (つまり) または型ガード (つまり) を削除する必要this.props.fooがあります。デフォルトの prop 値は実際には未定義にならないことを意味するため、これは面倒ですが、TS はこのフローを理解していませんでした。これが、TS 3.0 が の明示的なサポートを追加した主な理由の 1 つです。possibly undefinedthis.props.foo!if (this.props.foo) ...undefineddefaultProps

TypeScript 2.1 より前

これは同じように機能しますが、Partial型がないPartial<>ため、必要なすべての小道具のデフォルト値を省略して指定するか (それらのデフォルトは決して使用されません)、明示的な型注釈を完全に省略します。

機能コンポーネントを使用したデフォルトの小道具

defaultProps関数コンポーネントでも使用できますが、TypeScript が関数について認識できるように、( in before version ) インターフェイスにFunctionComponent関数StatelessComponent@types/react入力する必要があります。16.7.2defaultProps

interface PageProps {
  foo?: string;
  bar: number;
}

const PageComponent: FunctionComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

は TS 2.1+ でパーシャルとして既に指定されているPartial<PageProps>ため、どこでも使用する必要はありません。FunctionComponent.defaultProps

別の良い方法 (これは私が使用するものです) は、propsパラメーターを分解し、デフォルト値を直接割り当てることです。

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

その後、まったく必要ありませんdefaultProps!React は常に明示的に値を渡すため、関数コンポーネントで提供する場合、デフォルトのパラメーター値よりも優先されることに注意してください(したがって、パラメーターが未定義になることはなく、デフォルトのパラメーターは決して使用されません)。両方ではなく、どちらか一方。defaultPropsdefaultProps

于 2016-05-17T16:58:56.397 に答える
19

Typescript 2.1+ では、インターフェイス プロパティをオプションにする代わりにPartial < T >を使用します。

export interface Props {
    obj: Model,
    a: boolean
    b: boolean
}

public static defaultProps: Partial<Props> = {
    a: true
};
于 2017-02-23T05:37:02.393 に答える
4

受け入れられた回答に関する@pamelusのコメントから:

すべてのインターフェイス プロパティをオプションにする (悪い) か、すべての必須フィールドにもデフォルト値を指定する (不必要なボイラープレート) か、defaultProps でタイプを指定しないようにする必要があります。

実は Typescript のインターフェース継承が使えます。結果のコードは、少しだけ冗長になります。

interface OptionalGoogleAdsProps {
    format?: string;
    className?: string;
    style?: any;
    scriptSrc?: string
}

interface GoogleAdsProps extends OptionalGoogleAdsProps {
    client: string;
    slot: string;
}


/**
 * Inspired by https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js
 */
export default class GoogleAds extends React.Component<GoogleAdsProps, void> {
    public static defaultProps: OptionalGoogleAdsProps = {
        format: "auto",
        style: { display: 'block' },
        scriptSrc: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
    };
于 2017-02-17T09:36:04.797 に答える