Problem: The interface of Stateless Functional Component
is given as
interface SFC<P = {}> { (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null; propTypes?: ValidationMap<P>; }
The prop type of my component is also generic as:
interface Prop<V>{ num: V; }
How to properly define my component? as:
const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>
gives an error at character 27
that Cannot find name 'T'
Here is :Typescript Playground of modified example
MyFindings:
1:Typescript 2.9.1 support Stateful Generic Component: http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#generic-type-arguments-in-jsx-elements
class myCom<T> extends React.Component<Prop<T>, any> { render() { return <div>test</div>; } }
2: Extending SFC
to make a new interface as mentioned in following answer would make component's prop type as any
: Typescript React stateless function with generic parameter/return types which I don't want. I want to give proper type for my prop
You can't use generics like this:
const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>
The TypeScript spec states:
A construct of the form
< T > ( ... ) => { ... }
could be parsed as an arrow function expression with a type parameter or a type assertion applied to an arrow function with no type parameter.
source; Microsoft/TypeScript spec.md
Your declaration doesn't match the pattern defined in the TypeScript spec, therefore it wont work.
You can however don't use the SFC interface and just declare it yourself.
interface Prop<V> { num: V; } // normal function function Abc<T extends string | number>(props: Prop<T>): React.ReactElement<Prop<T>> { return <div />; } // const lambda function const Abc: <T extends string | number>(p: Prop<T>) => React.ReactElement<Prop<T>> = (props) => { return <div /> }; export default function App() { return ( <React.Fragment> <Abc<number> num={1} /> <Abc<string> num="abc" /> <Abc<string> num={1} /> // string expected but was number </React.Fragment> ); }
There's a pattern to mitigate this issue by declaring generic component type alias outside of component and then simply asserting it when you need it.
Not as pretty, but still reusable and strict.
interface IMyComponentProps<T> { name: string type: T } // instead of inline with component assignment type MyComponentI<T = any> = React.FC<IMyComponentProps<T>> const MyComponent: MyComponentI = props => <p {...props}>Hello</p> const TypedComponent = MyComponent as MyComponentI<number>
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