propTypes vs typescript types in React components
Prop types validate’s react component’s prop types in runtime and provide warnings in browser console if the sent prop is missing or the value is incorrect.
Typescript Types on the other hand works on compile time, they work more like a strict type system and will complain during compile time for incorrect types and even result in build failure.
Typescript Types:
Advantages:
- They are more strict in nature and force developers to fix prop types if incorrect or pass prop which is required else they may fail the production build
- TypeScript types have wide variety of types available which are not available in propTypes and complex types can be written better in typescript
- Function signatures can be declared in typescript types but not in propTypes. Consider this example
type ChildProps = {onClick(value: number): void;};function Child(props: ChildProps) { return ( <button type="button" onClick={() => props.onClick('1')}> Click Me </button> );}export function DummyComponent() { const foo = () => { console.log('Some Logic here'); }; return <Child onClick={foo} />;}
- Here in Child’s Prop types we have declared that onClick will accept an argument as number so in my code when we are passing parameter to function onClick typescript will warn me that you need to send an argument of type number because of the signature. This is possible in PropTypes also using custom propTypes validators, but not easy and requires a lot of effort.
Disadvantages:
- All the build failure and strictness we talked about will only work in typescript files and will not work with JS files until you explicitly enabled checkJS option via tsconfig or put a
@ts-check
comment on top of your JS file. That will tell the TSC compiler to check this file as an untyped TS file. The problem which you might face here is that if your application is mostly JS and you are getting started with typescript then it will throw errors for all of your application which may be hard to fix and a lot of effort will be required. Or If your code is mostly in Typescript and for some part you want to use javascript for some reason even for that file it will be difficult to type the files in JS as you will have to use JSDOC comments which may end up being a mess and hard to manage if your JS file or functions are complex. - If some data types depends on api data, and the entire api response type is defined incorrectly on FE your code might break at runtime if the api response is in a different shape, but typescript wouldn’t complain
PropTypes:
Advantages:
- Plain and simple to get started with, is supported by both JS and TS.
- Runs during run time so will give a warning about incorrect mentioned types which come from api or come dynamically. This only works in development but is helpful, because it gives you a hint (which may or may not be better than the default javascript error message) about what might be wrong if your code breaks due to incorrect api response
- Won’t break the build even if some types are wrong. Though it is not really an advantage but for developers who are new and just getting started with web development and are not familiar with TS to them it feels like native JS where language won’t complain about anything.
Disadvantages:
- Doesn’t enforce type error to developers, simply shows an error in the console which developers may ignore and code might contain some bugs due to incorrect types.
- Works in Run time which means no design time checking or breaking the code to fix the types.
- Supports only a limited set of types and sometimes writing a complex type can be hard with prop types and you might need to write your custom prop type which is hard to maintain and require a lot of effort.
- Prop types won’t break your build as they work on run time and are not added to the production bundle. Which will result in unexpected bugs in production due to wrong types and methods used on those wrong types which may break your application in production.
Which one to use
There is not much sense to maintain both of them in code, and since ts types are more strict in nature and have additional benefits added to it like type suggestions and static type checking and type errors. We feel typescript types are a better approach here to go with.
Though this doesn’t mean we should ignore prop types completely. There are cases where we want to maintain both.
- For JS and TS components that will be used by plain JavaScript, proptypes are an easy way to expose type information. (If your IDE supports typescript, it might still be able to get some intellisense from TS components into the js consumer. For js components consumed in js consumers, it is still possible to use type definitions to expose types if your IDE supports typescript)
- When using the data from an external source like API. PropTypes will help here because they validate data on run time and if some of the data type is wrong then you will get an error that this type is wrong.
- Using data from a library that may not have adequate or accurate typings, if any. PropTypes will be helpful here as they validate on run time and will give a warning that the passed prop is not matching the expected prop type. Here we write the prop types on the consumer to whoever the data from that library is being sent.
- We are in a migration phase to typescript and our code base is still 98% in JS, so there is good scope that some of our newly created components will be written in typescript but the consumer of those components will be a javascript file and it might be difficult to migrate the entire consumer to typescript, so in this case we still want to maintain the proptypes as the consumer will be able to get some hints from VScode from propTypes and consumer will be able to see the invalid prop types warning in the console.