web-dev-qa-db-ja.com

TypeScript / JSXの既存のHTML要素に属性を追加するにはどうすればよいですか?

すべてのネイティブHTML要素属性をカスタム属性で適切に追加/拡張する方法を知っている人はいますか?

インターフェイスをマージするためのTypeScriptドキュメント を使用して、私はこれを実行できると思いました:

interface HTMLElement {
    block?: BEM.Block;
    element?: BEM.Element;
    modifiers?: BEM.Modifiers;
}

<div block="foo" />; // error

しかし、vscode 1.6.1(最新)で次のIntellisenseエラーが発生します。

[ts]プロパティ 'block'はタイプ 'HTMLProps'に存在しません。

彼らが参照しているHTMLPropsReact.HTMLProps<T>およびdiv要素は、次のように使用するように宣言されています。

namespace JSX {
    interface IntrinsicElements {
        div: React.HTMLProps<HTMLDivElement>
    }
}

divを再宣言してみましたが、役に立ちませんでした。

関連: https://github.com/Microsoft/TypeScript/issues/11684

編集:これが私のために働いた結果です:

declare module 'react' {
    interface HTMLAttributes<T> extends DOMAttributes<T> {
        block?: string
        element?: string
        modifiers?: Modifiers // <-- custom interface
    }
}
23
jedmao

古いバージョンの型定義ファイル(v0.14)のように見えますが、インターフェースはグローバルReact名前空間の下で単純に宣言されていたため、以前は標準のマージ構文を使用できました。

declare namespace React {

    interface HTMLProps<T> extends HTMLAttributes, ClassAttributes<T> {
    }
}

ただし、新しいバージョンのd.tsファイル(v15.0)では、モジュール内のすべてが宣言されています。モジュールはマージをサポートしていないので、私の知る限り、現時点での唯一のオプションはmodule augmentationhttps://www.typescriptlang.org/docs/handbook/declaration-merging.html

私は次の実験をしました、そしてそれは私のために働きました:

import * as React from 'react';

declare module 'react' {
     interface HTMLProps<T> {
        block?:string;
        element?:string;
        modifiers?:string;
    }

}

export const Foo = () => {

    return (
        <div block="123" element="456">
        </div>
    )
};

明らかにこれは非常に退屈な作業です。TypeScriptハンドブックの例に示すように、オーグメンテーションコードを別のファイルに入れてインポ​​ートすることができます。

import * as React from 'react';
import './react_augmented';

しかし、それはまだかなり汚れています。したがって、タイプ定義ファイルのコントリビューターで問題に対処するのが最善の方法です。

9
Edwin

魅力的な createElement 置換を使用して、すべての要素にcssプロップを追加したいと思いました。

受け入れられた答えに追加するために、モジュール拡張はトリックを行うようですが、HTMLPropsは非入力要素に対してのみ機能しました。拡張する正しいインターフェースはHTMLAttributesSVGAttributesのようです。

declare module 'react' {
  interface HTMLAttributes<T> {
    css?: any
  }

  interface SVGAttributes<T> {
    css?: any
  }
}

すべてのコンポーネントでモジュール拡張をインポートしないようにするには、createElementを再エクスポートします。

// createElement.ts
import { createElement } from 'glamor/react'

declare module 'react' {
  interface HTMLAttributes<T> {
    css?: any
  }

  interface SVGAttributes<T> {
    css?: any
  }
}

export default createElement

次に、このtsconfigでJSXにcreateElementを使用するようTSに指示します。

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement"
  }
}

使用法:

// MyComponent.tsx
import createElement from './createElement'

export default function MyComponent() {
  return <div css={{ color: 'red' }} />
}
6
jschr

最新の例(2019年5月)

Reactタイプ定義ファイル(デフォルト-index.d.tscreate-react-app)すべての標準HTML要素と既知の属性のリストが含まれています。

カスタムHTML属性を許可するには、そのタイプを定義する必要があります。 HTMLAttributesインターフェースを拡張することでそれを行います:

declare module 'react' {
  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
    // extends React's HTMLAttributes
    custom?: string;
  }
}
1
yuval.bl

Vueの場合、次のように機能します。

declare module 'vue-tsx-support/types/dom' {
    interface InputHTMLAttributes  {
        autocorrect: string;
        autocapitalize
    }
}
0