-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typescript support #7
Comments
The best workaround is something like: import { Component, ReactNode } from 'react'
interface ParentProps<T extends object = any> {
children?: ReactNode[] | ((props: T) => ReactNode)
}
// Infer the argument types of a function
type In<T> = T extends (...args: infer U) => any ? U : []
/** The functional "render children" prop */
type ChildFunction<T extends ParentProps> = Exclude<
T['children'],
ReactNode[] | undefined
>
// Component with render props
type RPC = Component<ParentProps> | ((props: ParentProps) => ReactNode)
/** Extract the render props of a component */
export type RenderProps<T extends RPC> = In<
ChildFunction<T extends Component<ParentProps> ? T['props'] : In<T>[0]>
>[0] And then: import { Component, ReactNode } from 'react'
import epitath, { RenderProps } from 'epitath'
declare const Foo: (props: FooProps) => ReactNode
declare type FooProps = {
children?: (value: { a: number }) => ReactNode
}
declare class Bar extends Component<BarProps> {}
declare type BarProps = {
children?: (value: { b: number }) => ReactNode
}
const App = epitath(function* () {
const { a }: RenderProps<typeof Foo> = yield <Foo />
const { b }: RenderProps<Bar> = yield <Bar />
return a + b
}) Example: https://codesandbox.io/s/qqonn05154?view=editor (note: CodeSandbox is using TS 2.7 so not exactly a working example right now) |
That is interesting! I don't know much about TS myself, but I'm going to read more about those and see if we can ship support right away |
Nice. Also, I opened microsoft/TypeScript#27267 to see if better support for immutable generators could be added. |
Just to share my config which works so-and-so (having typing issues with yielded elements not having an explicit children prop) declare module "epitath" {
import * as React from "react"
const epitath: <P extends {}>(
Component: (props: P) => IterableIterator<React.ReactElement<any>>
) => React.ComponentType<P>
export default epitath
}
// interface Props { foo: string }
// Usage: const FooComponent = epitath<Props>(function* ({ foo }) { ... }) |
FYI meanwhile we discuss about this, ReasonML implementation of Epitath gave free type inference support |
I've been looking into adding Typescript support to this library. Here are the issues I encountered.
JSX factory invocations (eg:
<Foo />
) returnReactElement<any>
(but a fix is on the way), which means we can't infer the prop types of any returned elementsThis is only true if you explicitly type your stateless component using@types/react
does not allow thechildren
prop to be a function (at least with "stateless components")React.SFC
Typescript cannot infer what
yield
returns, which means render props are untyped by default yield operator in generator functions has any return type microsoft/TypeScript#26959Now I'm wondering if "
yield
to wrap the nextyield
orreturn
" is worth the lack of type safety, or if I should bite the bullet on using render props without this library. 😞If generators were always immutable in Javascript, this would be a lot easier.
The text was updated successfully, but these errors were encountered: