JSX TypeScript definitions override for custom framework's components?

I’m working on an opensource JS framework and I want to use JSX with typescript for it’s components. But I have an issue with type definitions for JSX

TS expects:

<Header title="Hello World" />

to be (for any react-like framework):

function Header(props: { title: string }) : JSXElement

While in this framework the actual type is based on Observables (RxJS):

function Header(props: Observable<{ title: string }>) : JSXElement | Observable<JSXElement>

E.g. a simple h1 header component:

function Header(props$) { // take in a stream of updates
  return props$.pipe(     // return a stream of JSX updates
    map(props => <h1>{ props.title }</h1>)

So, components receive an Observable of properties and return a static JSX element or a stream of JSX elements.

UPD to clarify: The framework already works as I described, the typings is the issue. Observables are handled in the engine runtime, not in the transformation phase, so JSX transformation to createElement is fine. I just need to adjust typings for TSX, something like:

// current:
createElement<P>(fn : (props: P) => JSXElement, props: P, ...children: JSXElement[])

// should be:
createElement<P>(fn : (props: Observable<P>) => JSXElement, props: P, ...children: JSXElement[])

I see that one can partially customize JSX but I haven’t found a way to override that. I’ve tried to override JSX.Element and JSX.ElementType w/o any visible change to typings outcome.

Is it even possible to do this override?

What types/interfaces should I override?


~~I’m not linking the repo not to be suspected in advertising~~

UPD: For details, you can find the framework here:

Stack Overflow Asked by kos on January 2, 2021

2 Answers

2 Answers

It seems like LibraryManagedAttributes can do the override I was looking for.

Preact uses it to add defaultProps to component types:

type LibraryManagedAttributes<Component, Props> = Component extends {
    defaultProps: infer Defaults;
    ? Defaultize<Props, Defaults>
    : Props;

So I similarly overrode it with:

type LibraryManagedAttributes<Component, Props> =
    Props extends Observable<infer O>
    ? O
    : EmptyProps;

interface EmptyProps {}

EmptyProps is a hack to ensure components w/o proper type won't accept attributes.

It seem to work (at least, affect the types):

code example

NOTE: as shown in this screenshot, you'll need to override built-in TS definitions for JSX via a namespace global.[LIB_NS].JSX or directly via global.JSX. For more details, see the section at the very bottom of official docs:

Big thanks goes to Josep M Sobrepere for giving me a hint on preact's LibraryManagedAttributes override! ?

Please, feel free to add your answer if you know more details

Correct answer by kos on January 2, 2021

Try overriding and customizing node_modules/@types/react/index.d.ts and node_modules/@babel/types/lib/index.d.ts I was able to set React.FC to the type {foo: 'bar'} and also update the JSXElement to have the same type, and then write a component that returns that object & renders it without producing a type error. I am testing by modifying the typings in a React project. I didn't test with your library, but I think the key is to not load the React typings and instead load your own typings. The fact the typings are effectively global is the larger issue, consumers of your project may need separate tsconfig files to use both libs in the same project with this approach.

Answered by Josh Ribakoff on January 2, 2021

Add your own answers!

Related Questions

How to Deserialize a list of objects from json in flutter

8  Asked on January 28, 2021 by gainz


How to pass input variable in structure directive?

1  Asked on January 27, 2021 by alice-messis


How to iterate over a list of floats in python

4  Asked on January 27, 2021 by joeyhoward988


Can I run docker system prune -a without downtime

1  Asked on January 27, 2021 by aswin-george


Calculating total Price of groceries with execptions in Python

4  Asked on January 27, 2021 by shemtheultimate


handling multiple useState inside conditional ternary

2  Asked on January 27, 2021 by kachi-cheong


react-native existing app crash on Android 4.1

0  Asked on January 27, 2021 by s-leg3ndz


HTML table widths set proportionally

1  Asked on January 27, 2021 by mayur-arora


Alsa issues on Raspberry pi

1  Asked on January 27, 2021 by suraj-hebbar-shankar


How to merge dictionaries with the same key and value in Python

1  Asked on January 26, 2021 by arbin-bulaybulay


AJAX switching HTML

1  Asked on January 26, 2021 by mimi


Using request to return a json value

1  Asked on January 26, 2021 by gta-sprx


Ask a Question

Get help from others!

© 2022 All rights reserved.