Hur kan jag utöka attributen för jsx-element i TypeScript tsx-kod?


test.tsx

<img onerror="this.style.display='none'" height="178" cmd="start" />

avkastning

error TS2339: Property 'onerror' does not exist on type 'HTMLAttributes'.

Så jag lägger till JSX-delen ovan i test.tsx:

namespace JSX {
  interface HTMLAttributes {
    onerror?: any; // 1. attempt: add the missing onerror attribute
  }
  interface IntrinsicElements {
    img: any // 2. attempt: generally override the type of img, allowing anything
  }
}

Men utan effekt. Hmm?

Hur kan jag lokalt lägga till attribut till JSX-koden som jag vill använda?

Jag vet att jag kan brutalhålla den importerade typer-filen, men jag skulle vilja veta om det finns ett lokalt sätt.

redigera: Utöver attributet onerror (som 'felaktigt' saknas i preact.d.ts) skulle jag i allmänhet vilja veta hur jag kan lägga till tillfälliga attribut till inbyggda eller till och med mina egna element. Nyfiket och fantastiskt, TypeScript klagar aldrig på "data-*"-attribut, som jag troligtvis kommer att byta över till (vill ändå vara en bra html5-utvecklare). Men frågan om utökning av gränssnittet HTMLAttributes är fortfarande öppen för mig.

Svar #1

Du behöver omdefiniera Reacts ImgHTMLAttributes<T>

import * as React from 'react'
declare module 'react' {
    interface ImgHTMLAttributes<T>  {
         onError?: ReactEventHandler<T>;
    }
}

Eller ännu bättre, definiera om det på DOMAttributes:

import * as React from 'react'
declare module 'react' {
    interface DOMAttributes<T> {
        onError?: ReactEventHandler<T>;
    }
}

Redigera

Frågan avser preact, eftersom det använder namnrymder behöver vi några trippel-snitt för att få saker att fungera:

react.ext.d.ts

/// <reference path="./node_modules/preact/dist/preact.d.ts" />
declare namespace JSX {
    interface HTMLAttributes {
        onError: JSX.GenericEventHandler;
    }
}

test.tsx

/// <reference path="./node_modules/preact/dist/preact.d.ts" />
/// <reference path="react.ext.d.ts" />
import * as React from 'preact'
let x = <img height="178" onError={o => console.log(o)} />;

Svar #2

Det finns redan, men med ett versalt E, vilket kan ses i definitionsfilen.

Men det kommer inte att hjälpa dig eftersom (såvitt jag vet) kan du inte bara lägga in en sträng där och förvänta dig att den ska utvärderas.
Och faktiskt kommer kompilatorn att klaga och säga:

Type '{ onError: "this.style.display='none'"; height: "178"; }' is not assignable to type 'DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>'.
  Type '{ onError: "this.style.display='none'"; height: "178"; }' is not assignable to type 'ImgHTMLAttributes<HTMLImageElement>'.
    Types of property 'onError' are incompatible.
      Type '"this.style.display='none'"' is not assignable to type '(event: SyntheticEvent<HTMLImageElement>) => void'.

Istället behöver du göra något som:

class MyComponent {
    private img: HTMLImageElement;

    render() {
        return <img height="178" onError={ this.onError.bind(this) } ref={ el => this.img = el } />;
    }

    private onError() {
        this.img.style.display = "none";
    }
}

Redigera

Från vad jag ser i definitionsfilen för preact exporteras endast preact-delen som ett modul så du kan bara utöka det.
Lyckligtvis innehåller definitionerna PreactHTMLAttributes som sedan utökas av JSX.HTMLAttributes, så du kan göra så här:

declare module "preact" {
    interface PreactHTMLAttributes {
        onerror?: any;
    }
}