-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Support setting React PropTypes using TypeScript types #4833
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
Comments
PropTypes is used for type checking in developement mode. TypeScript already does type checking at compile time, i don't think that you need PropTypes if you use TypeScript. |
Hmm, that's true, I guess :) |
Although, then again (sorry for the change-of-mind), props aren't passed as an argument to the component, right? Thus, there isn't really a place in the component to define what its given properties should look like... |
//cc: @RyanCavanaugh |
Your props should be defined in an interface which is passed as a type parameter to |
Ah, that sounds good - sorry, I only have experience with React's non-ES6 syntax since I'm using mixins, so if you can define the interface for your props using the class syntax, that should cover it :) |
no worries :) as some additional advice, you'll want your props to extend interface IFooProps extends React.Props<Foo> {
// ...
}
interface IFooState {
// ...
}
class Foo extends React.Component<IFooProps, IFooState> {
// ...
} |
I might be missing something, but without proptypes support, how do I write the equivalent of var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
return (
<div>
{this.props.children} // This must be exactly one element or it will throw.
</div>
);
}
}); interface IMyComponentProps extends React.Props<MyComponent> {
}
interface IFooState {
}
class MyComponent extends React.Component<IMyComponentProps, IMyComponentState> {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
React.render(
<MyComponent>Body</MyComponent>,
body
); makes the children optional, but interface IMyComponentProps extends React.Props<MyComponent> {
children: React.ReactChild | {} | any[] | boolean;
} yields the compilation error |
There's currently no type system enforcement of child elements. We looked into this but a) there doesn't seem to be a lot of code that has meaningful constraints on its children and b) we would have had to encode a ton of very React-specific semantics into the type system, which we weren't comfortable doing at this point. |
What about the case when building a react library to be used by others. Others may not be using typescript. It would be nice to have a way to generate PropTypes when creating the distributed lib so other developers will be able to get PropType validation during development when using the library. React then strips theses away when building production. |
as the @TheSharpieOne said, this is stopping us from porting main libraries to typescript since we have multiple consumers which in turn stops us from migrating the consumers to typescript (since it feels to be rather error prone to manually add both and keep them in sync) |
what @TheSharpieOne and @TobiasBales said. We kinda need support for it. |
I came up with an idea, that satisfies both typescript and react runtime prop validation, but it has flaws. Say we have a component named Icon, it has two props name and size. const iconPropTypes = {
name: pt.string.isRequired as any as string,
size: pt.number as any as number
}
type TProps = typeof iconPropTypes
class Icon extends Component<TProps, {}> {
...component content
}
Icon['propTypes'] = iconPropTypes The problem is obvious in typescript size is required when it's not supposed to, and I have not found a solution to work this around. |
The effective difference between React PropTypes and TypeScript types is that, while TypeScript type annotations can describe what JSON schema the server should deliver, React detects what is actually delivered. If the wrong data is delivered to the client, React PropTypes will give us good error messages while the transpired TypeScript will die without explanation. While the two systems clearly overlap, this feature can be justified in serving to automatically check server data at runtime. Also, note that React PropTypes are fairly limited ("this property must be an object") while TypeScript could generate a more complete custom validator ("this property must be an object with an integer id and a string name") |
React PropTypes can describe objects in more detail, e.g. |
@TobiasBales - thanks for that; you're right. I wonder whether it is possible to write a PropTypes object for each type using the TypeScript compiler API and type checker. Notice how the example lets you find type and and member info, build a complex object describing the type, and output structured content. You could do something like;
Not as easy as full language support, and it's just an idea, but possibly something you could get working with a bit of hacking about. |
Hey all, would prop-types-ts get you close to what you want? Instead of creating proptypes out of TypeScript types, it allows you to make TypeScript types from proptypes. |
Some libraries written by TS, compiled to JavaScript and published on npm registry, like https://github.com/ant-design/ant-design-mobile, is there a way to use its propTypes in JavaScript? |
@omril1 what ? |
This might help someone, if you want to make a interface Props {
name: string
}
export class Person extends React.Component<Props, {}> If you later try interface Props {
name?: string
} With the above interface TypeScript won't complain whenever we do |
For anybody still interested in the original suggestion, I've put together a proof-of-concept webpack loader here https://github.com/grncdr/ts-react-loader#what-it-does that will inject static |
Maybe re-open this issue @Vinnl ? My use case is when using ts and non-ts files at the same time (e.g. when I incrementally rewrite my React components to TypeScript). My non-ts files don't warn me when I pass the wrong props, and I have no runtime checks either. |
@jessedvrs Now that I understand TypeScript better, I've become convinced that React's PropTypes and TypeScript types serve different purposes, namely runtime vs. compile-time checks - and TypeScript typically does not try to influence run-time behaviour. That said, I think your use case points to a bigger problem with TypeScript, not even specific to prop-types, namely: dealing with less-strict environments (such as TypeScript with looser configuration, or plain Javascript). If you use TypeScript in strict mode, you can write a function that receives a I am currently inclined to say no, and to add those checks as such:
(although I'm not sure if that would work as expected, as I have no libraries in TypeScript) An alternative is to not do the prop-type checking at all - there's already a lot of assumptions built-in in regular Javascript. If you need the extra guarantees in a file, that file should be converted to TypeScript. In any case, I happen to have reported the more general case here: #12615 |
Thanks for your quick response @Vinnl :) You could indeed state that the strictness of the library user should match the strictness of the library itself, so users could just upgrade to TypeScript and the problem would be solved. TypeScript and prop-types do indeed serve different technical purposes. So that is why this is not a TypeScript issue and this issue should stay closed, I agree. But we do use a TypeScript interface in replacement of React's PropTypes, so in the end it does serve the same purpose regardless of the time difference (runtime, compile-time). And that is property validation when implementing React components. That being said, your code example is indeed my current solution. Which is to manually throw or log errors when the value doesn't match the type, but this is exactly what React's PropTypes already do. So I'm looking to find a solution to add React's PropTypes based on the TypeScript interface. I personally think this should be something explicit, for example with decorators or something. |
I'm not sure how practical this would be, but since TypeScript is now supporting React's JSX syntax, it could perhaps provide more syntactic sugar for a common React pattern? Namely, that of setting PropTypes, requirements for the structure of property arguments for React components. Sounds like TypeScript's syntax should be able to remove a lot of the boilerplate there.
The text was updated successfully, but these errors were encountered: