6

I'm working on accessibility and thought "I'll just make alt a required attribute in my project." My aim is for all img tags in my react app to complain if an alt attribute has not been provided. So, I created a .d.ts file where I have added the following:

import { HTMLAttributes } from 'react';

declare module 'react' {
  export interface ImgHTMLAttributes<T> extends HTMLAttributes<T> {
    alt: string;
  }
}

I'm getting these errors:

All declarations of 'alt' must have identical modifiers.

Subsequent property declarations must have the same type. Property 'alt' must be of type 'string | undefined', but here has type 'string'.

Is there a way to indicate that I'm trying to override, and not extend? Or is there a better way to go about this?

drewwyatt
  • 5,989
  • 15
  • 60
  • 106
  • Since this isn't natural behaviour for ``, you possibly need a custom `Img` wrapper component that would enforce a prop you need. See also https://stackoverflow.com/questions/44675647/extend-a-namespace-from-package-typings . I could forget something but it seems there's no good way. – Estus Flask Dec 07 '18 at 21:05

2 Answers2

0

I guess that's not possible, because Typescript sees no difference (hierarchically) between your types and types in node_modules.

So I normally go with defining my own types, and everything's OK:

import { ImgHTMLAttributes } from 'react';

export interface IMyImgHTMLAttributes extends ImgHTMLAttributes<any> {
  alt: string;
}

P.S. However, I don't know if this is an appropriate workaround for your special case (I am not familiar enough with React).

Nurbol Alpysbayev
  • 19,522
  • 3
  • 54
  • 89
  • I'm afraid you are right. This seems to be the answer I keep finding while searching. This doesn't quite fix my case since JSX `img` tags are automatically typed as `ImgHTMLAttributes `. I was hoping to not have to create a wrapper. I can probably solve this with tslint if this can't be solved with declaration merging though. – drewwyatt Dec 07 '18 at 21:16
  • @drewwyatt I am sorry about that. What's the idea with tslint? My workaround would be to write a small node utility to run (in the CI pipeline) and check if all `` tags has `alt` property. Seems not too difficult. – Nurbol Alpysbayev Dec 07 '18 at 21:19
  • tslint would do the same. Then you get CI support (if linting fails) **and** IDE warnings/errors. You also get the benefit of the parsing happening at the AST level, so you aren't just comparing strings. – drewwyatt Dec 07 '18 at 21:58
  • @drewwyatt But how tslint will do this? Isn't it for style checking only? BTW I have an idea but it's somewhat hackish (and don't know if it'll work). `exclude` in tsconfig the file with `ImgHTMLAttributes` types, and copy it to your project with the appropriate modifications. – Nurbol Alpysbayev Dec 07 '18 at 22:03
0

Option 1: Wrapper Component

Instead of using <img/> elements directly, you can write a simple wrapper component that makes alt a required attribute:

function Img({src, alt}: {src: string, alt: string}) {
  return <img src={src} alt={alt} />;
}

Option 2: Linter

You can also use a linter to throw a warning or error when you create an <img/> without an alt prop. If you're using eslint, I found a plugin called jsx-eslint / eslint-plugin-jsx-a11y that defines the alt-text rule.

island
  • 43
  • 5