Made ComponentOverride generic (#42603)

Fixes type issues such as https://stackoverflow.com/questions/60382399/why-is-type-sfcanchorprops-not-assignable-to-type-sfc.
This commit is contained in:
Sun Knudsen
2020-02-28 13:50:06 -05:00
committed by GitHub
parent d49a96d85d
commit b6ffefefca
2 changed files with 107 additions and 25 deletions

View File

@@ -1,12 +1,13 @@
// Type definitions for markdown-to-jsx 6.9
// Type definitions for markdown-to-jsx 6.11
// Project: https://probablyup.github.io/markdown-to-jsx
// Definitions by: Elizabeth Craig <https://github.com/ecraig12345>
// Sun Knudsen <https://github.com/sunknudsen>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.8
import * as React from 'react';
export default class Markdown extends React.Component<MarkdownProps> { }
export default class Markdown extends React.Component<MarkdownProps> {}
export interface MarkdownProps extends React.HTMLAttributes<HTMLElement> {
options?: MarkdownOptions;
@@ -15,10 +16,14 @@ export interface MarkdownProps extends React.HTMLAttributes<HTMLElement> {
children?: React.ReactNode;
}
export type ComponentOverride = string | React.ComponentClass | React.SFC | {
component: string | React.ComponentClass | React.SFC;
props?: any;
};
export type ComponentOverride<P = any, S = any> =
| string
| React.ComponentClass<P, S>
| React.SFC<P>
| {
component: string | React.ComponentClass<P, S> | React.SFC<P>;
props?: any;
};
export interface MarkdownOptions {
/** Force all input strings to use block layout. */
@@ -70,9 +75,10 @@ export interface MarkdownOptions {
type: React.SFC<P> | React.ComponentClass<P> | string,
// This typing is copied from React
// tslint:disable-next-line:no-null-undefined-union
props?: React.Attributes & P | null,
props?: (React.Attributes & P) | null,
// tslint:disable-next-line:no-null-undefined-union
...children: React.ReactNode[]) => React.ReactElement<P>;
...children: React.ReactNode[]
) => React.ReactElement<P>;
/** Custom function to generate an HTML id from headings. */
slugify?: (text: string) => string;

View File

@@ -9,9 +9,70 @@ compiler('Hello there old chap!', { forceBlock: true });
<Markdown options={{ forceInline: true }}># You got it babe!</Markdown>;
const MyParagraph: React.FunctionComponent = ({ children, ...props }) => (
<div {...props}>{children}</div>
);
const MyParagraph: React.SFC = ({ children, ...props }) => <div {...props}>{children}</div>;
interface MySquareImageProps {
src: string;
alt?: string;
size?: number;
}
const MySquareImage = (props: MySquareImageProps) => {
let width: string | undefined;
let height: string | undefined;
if (props.size) {
width = `${props.size}px`;
height = `${props.size}px`;
}
return <img alt={props.alt} src={props.src} width={width} height={height} />;
};
interface MyStatelessRoundImageProps {
src: string;
alt?: string;
size?: number;
}
class MyStatelessRoundImage extends React.Component<MyStatelessRoundImageProps> {
render() {
let width: string | undefined;
let height: string | undefined;
if (this.props.size) {
width = `${this.props.size}px`;
height = `${this.props.size}px`;
}
return <img alt={this.props.alt} src={this.props.src} width={width} height={height} />;
}
}
interface MyRoundImageProps {
src: string;
alt?: string;
size?: number;
}
interface MyRoundImageState {
loading: boolean;
}
class MyRoundImage extends React.Component<MyRoundImageProps, MyRoundImageState> {
constructor(props: MyRoundImageProps) {
super(props);
this.state = {
loading: true,
};
}
render() {
let width: string | undefined;
let height: string | undefined;
if (this.props.size) {
width = `${this.props.size}px`;
height = `${this.props.size}px`;
}
return <img alt={this.props.alt} src={this.props.src} width={width} height={height} />;
}
}
render(
<Markdown
options={{
@@ -23,23 +84,41 @@ render(
},
},
h2: {
component: 'div'
component: 'div',
},
h3: {
component: 'span',
props: {
className: 'foo'
}
className: 'foo',
},
},
p: MyParagraph,
h4: 'h3',
MyParagraph
MyParagraph,
MySquareImage: {
component: MySquareImage,
props: {
size: 240,
},
},
MyRoundImage: {
component: MyRoundImage,
props: {
size: 240,
},
},
MyStatelessRoundImage: {
component: MyStatelessRoundImage,
props: {
size: 240,
},
},
},
}}
>
# Hello world!
</Markdown>,
document.body
</Markdown>,
document.body,
);
render(
@@ -47,19 +126,16 @@ render(
children="# Hello world"
options={{
createElement: <P extends {}>(
type: React.FunctionComponent<P> | React.ComponentClass<P> | string,
type: React.SFC<P> | React.ComponentClass<P> | string,
// This typing is copied from React
// tslint:disable-next-line:no-null-undefined-union
props?: React.Attributes & P | null,
props?: (React.Attributes & P) | null,
// tslint:disable-next-line:no-null-undefined-union
...children: React.ReactNode[]) => (
<div className="parent">
{React.createElement(type, props, children)}
</div>
)
...children: React.ReactNode[]
) => <div className="parent">{React.createElement(type, props, children)}</div>,
}}
/>,
document.body
document.body,
);
<Markdown options={{ slugify: str => str }}># </Markdown>;