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?
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!
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.
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!
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With