Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript type arguments in JSX nodes

Is there any way to specify type arguments for components rendered in JSX?

For example, consider this component:

interface SelectorProps<T> {
    selection: T;
    options: T[];
}

class Selector<T> extends React.Component<SelectorProps<T>, {}> {
    // ...
}

If I try to render this component in JSX:

<Selector selection="a" options={["a", "b", "c"]} />

I get these errors:

TS2322: Type 'string' is not assignable to type 'T'.

TS2322: Type 'string[]' is not assignable to type 'T[]'. Type 'string' is not assignable to type 'T'.

I would expect T to be inferred as string or else some way to specify T=string in <Selector>. Is there a solution?

The only workaround I have found is to extend the component to eliminate all type arguments:

class StringSelector extends Selector<string> { }
like image 453
Aaron Beall Avatar asked Nov 17 '16 21:11

Aaron Beall


People also ask

Can you use TypeScript in JSX?

TypeScript supports embedding, type checking, and compiling JSX directly to JavaScript.

What is the difference between TSX and JSX?

TypeScript is known as an Object-oriented programming language whereas JavaScript is a prototype based language. TypeScript has a feature known as Static typing but JavaScript does not support this feature. TypeScript supports Interfaces but JavaScript does not.

Is TypeScript better than JSX?

To conclude, JSX = JS, typescript is a superset of Javascript, and there is no comparison between JSX and TypeScript.

What is JSX element []?

What is JSX? JSX stands for JavaScript XML. JSX allows us to write HTML in React. JSX makes it easier to write and add HTML in React.


2 Answers

Generic JSX elements as described in https://github.com/Microsoft/TypeScript/issues/6395 are now supported - since TypeScript 2.9.

You should now be able to use:

 <Selector<string> selection="a" options={["a", "b", "c"]} />

See also: http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

like image 129
Philip Avatar answered Oct 20 '22 23:10

Philip


interface FooProps<T> { foo: T; }
class Foo<T> extends React.Component<FooProps<T>, any> {
  render() {
    return <div>{ JSON.stringify(this.props.foo) }</div>;
  }
}
type FooBar = new () => Foo<{bar: string}>;
const FooBar = Foo as FooBar;

class FooBarContainer extends React.Component<any, any> {
  render() {
    return <FooBar foo={{bar: 'works'}} />;
  }
}

FooBarContainer or <FooBar foo={{bar: 'works'}} /> should render: <div>{"bar":"works"}</div>

like image 33
StrikeForceZero Avatar answered Oct 20 '22 23:10

StrikeForceZero