Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript and Google AMP? Property 'amp-img' does not exist on type 'JSX.IntrinsicElements'

I have a node project running an express server that, when queried a news article with /amp in the url, returns the amp version of that article.

Due to the request of a client, these amp articles are built using React components that are in the end rendered to Static Markup. Here is one of the components:

import * as React from 'react';
import { Article_modulesByArticleId_edges_node } from '../../data/__generated__/Article';

// GraphQL auto generated type for the data that is sent to this component 
type Props = {
	module: Article_modulesByArticleId_edges_node;
};

export default (props: Props) => {
	const image = props.module.image;
	if (!image || !image.url || !image.title || !image.copyright) {
		return "";
	}

	return <amp-img alt={image.title} src={image.url} ... />
};

The problem? The project also uses typescript, which I am not overly familiar with.

When I try to use a custom AMP-HTML element, typescript throws this error message:

[ts] Property 'amp-img' does not exist on type 'JSX.IntrinsicElements'.

I haven't been able to find any node packages with the AMP types defined, and overall not a lot of discussion about Typescript and AMP. Does anyone have any suggestions? Do I have to write my own declarations for AMP elements?

like image 582
tannerbaum Avatar asked May 29 '18 13:05

tannerbaum


People also ask

How do you fix JSX element implicitly has Type any because no interface JSX IntrinsicElements exists?

To solve the error "JSX element implicitly has type 'any' because no interface 'JSX. IntrinsicElements' exists", make sure to install the typings for react running the command npm install --save-dev @types/react@latest @types/react-dom@latest and restart your IDE. Copied!

Does not exist JSX IntrinsicElements?

The error "Property does not exist on type 'JSX. IntrinsicElements'" occurs when a component's name starts with a lowercase letter. To solve the error, make sure to always start component names with a capital letter, install the types for React and restart your dev server.


2 Answers

So in the writing declarations of AMP elements front, it isn't so bad. There are three options:

// Any element you create will be accepted
declare namespace JSX {
	interface IntrinsicElements {
		[elemName: string]: any;
	}
}

// The elements you list here will be accepted, attributes don't matter
declare namespace JSX {
	interface IntrinsicElements {
		'amp-img': any;
	}
}

// The elements you list here will be accepted, and only with the attributes that you include here
declare namespace JSX {
	interface AmpImg {
		alt?: string;
		src?: string;
		width?: string;
		height?: string;
		layout?: string;
	}
	interface IntrinsicElements {
		'amp-img': AmpImg;
	}
}

The only downside with doing it manually like this is that you would have to update it yourself if the Amp spec changes. So let me know if there is currently another option.

Regardless, hope this helps someone!

like image 152
tannerbaum Avatar answered Sep 18 '22 13:09

tannerbaum


Inside a page, the answer given by @tannerbaum does not work for me as the namespace seems not used.

Instead, this did the trick for me:

declare global {
  namespace JSX {
    interface IntrinsicElements {
      [elemName: string]: any;
    }
  }
}
like image 40
Sicaa Avatar answered Sep 16 '22 13:09

Sicaa