Skip to content

Instantly share code, notes, and snippets.

@AlicanC
Last active April 19, 2020 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlicanC/51b5355880961c40049a70b88e2716b4 to your computer and use it in GitHub Desktop.
Save AlicanC/51b5355880961c40049a70b88e2716b4 to your computer and use it in GitHub Desktop.
// @flow
type Completion<TType: 'normal' | 'throw', TValue> = '/* internal */';
type NormalCompletion<TValue> = Completion<'normal', TValue>;
type ThrowCompletion<TValue> = Completion<'throw', TValue>;
function fetchNode() {
if (a) throw new NotAllowedError();
if (b) throw new NotFoundError();
if (c) return new ProfileNode();
return new UserNode();
}
// $CompletionType<typeof fetchNode> == NC<ProfileNode> | NC<UserNode> | TC<NotFoundError> | TC<NotAllowedError>
// $ReturnType<typeof Fn1> == ProfileNode | UserNode
// $ThrowType<typeof Fn1> == NotFoundError | NotAllowedError
try {
fetchNode()
} catch (error) {
// typeof error == NotFoundError | NotAllowedError
}
// React use case
type ReactComponent = () => NormalCompletion<React.Node> | ThrowCompletion<Promise> | ThrowCompletion<Error>;
type ErrorBoundary = () => NormalCompletion<React.Node>;
type SuspenseBoundary = () => NormalCompletion<React.Node> | ThrowCompletion<Error>;
type SimpleComponent = () => NormalCompletion<React.Node>;
// typeof ReactDOM.render == (Element<SimpleComponent>, HTMLElement) => any
function MyComponent() {
if (!cached) throw new Promise();
if (!condition) throw new Error();
return <div />;
}
ReactDOM.render(<MyComponent />); // Error, can throw Promise or Error
ReactDOM.render(<Suspense><MyComponent /></Suspense>); // Error, can throw Error
ReactDOM.render(<ErrorBoundary><Suspense><MyComponent /></Suspense></ErrorBoundary>); // OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment