Finding a good DX for props
in Typescript and React.
See Typescript wiki. See React TypeScript Cheatsheets
Interfaces/extends is suggested over creating intersection types.
- Adding type annotations, especially return types, can save the compiler a lot of work.
- instead
Interface1 | Interface2
useextend
- The perfect hover (destructured signature) duplicates two times the interface definition and should have no return type. (example1)
- Return types always break the hover info both when props in the signature are destructured or not. (example1)
- When signature is not destructured but later
props
is destructured we got proper type info on hover. (example2) - This is good news only when starting to write code. Hovering in another file gives no hints...
- Perfect hover is not achievable => don't rush for it => don't destructure in signature => use
props
and avoid duplication
useExample3(props: TExample = defaultProps)
this doesn't work (with deep objects).- This doesn't works: https://react-spectrum.adobe.com/react-aria/mergeProps.html
- This works (from lodash):
export function useExample3e(props: TExample) {
const props2 = defaultsDeep(props, defaultProps);
return props2;
}
When these combined props simply cannot be destructured in function signature. It results in an ugly destructuring repetition. See example4
.
export function useExample4({ variant, name, number, options }: TExample) {
const props2 = defaultsDeep({ variant, name, number, options }, defaultProps);
}
When default props are used there will be no destructuring errors like property not defined
. See example5, Example5
.
- Function signature, Default props should follow the rule above.
However:
- By default
JSX.Element
is added to function return type. (See it when hover on a component declared without return type likeexport function Example1(props: TExample) {}
) - So when we don't add a return type still don't break Best practices rules. (???) The code looks inconsistent compared to
.ts
but inferring works fine.