2

test.tsx

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

yields

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

So I add to test.tsx above the JSX part:

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
  }
}

But with no effect. Hmm?

How can I locally add attributes to the JSX code that i want to use?

I know that I can brutally hack the imported types file, but i would like to know if there is a local way.

edit: In addition to the onerror attribute (that is 'erroneously' missing in preact.d.ts) I would generally like to know how I can add ad-hoc attributes to intrinsic or even my own elements. Curiously and phantastically, typescript never complains about "data-*" attributes which I likely will switch over too (want to be a nice html5 dev anyway). But the question about expansion of interface HTMLAttributes is still open to me.

1
  • Btw, if you don't tag someone or comment on his answer, then he won't be notified. Commented Jan 25, 2018 at 21:13

2 Answers 2

4

You need to redefine react's ImgHTMLAttributes<T>

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

Or better yet redefine it on DOMAttributes:

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

Edit

The question refers to preact, since that uses namespaces we need some triple slashes to make things work:

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)} />;
Sign up to request clarification or add additional context in comments.

1 Comment

thx. Using preact with a somewhat different preact.d.ts . HTMLAttributes is in JSX namespace outside of namespace preact. Tried everything around your suggestion but no success.
2

It already exists, but with a capital E, as can be seen in the definition file.

But that won't help you because (as far as I know) you can't just put a string in there and expect it to be evaluated.
And indeed the compiler will complain saying:

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'.

Instead, you need to do something like:

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

Edit

From what I see in the definition file for preact only the preact part is exported as a module so you can only augment that.
Luckily the definitions contain PreactHTMLAttributes which is then extended by the JSX.HTMLAttributes, so you can do this:

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

3 Comments

thx for your input. i use preact.d.ts where its missing. so this one should be added there anyway, will do so. then, you are right, this is an event, so should be handled like one. my question focused on "onerror" but i have other expando attributes as well. which I still would like to know how to add. I will expand my question. maybe you have an idea on that too.
Check my revised answer
excellent! that was what I wanted to understand. have to update myself about namespaces and modules. thx so much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.