You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Feb 16, 2021. It is now read-only.
The documentation suggests a withDefaults React HOC. We've been using this in production and we love it, but it has an important issue which I'd like to note for others, and potentially fix with updated docs.
TypeScript does not distinguish optional properties (e.g. values either missing or provided with a given type) from undefined: microsoft/TypeScript#13195
This means that an undefined prop may be passed to a component whose prop is marked as optional—not undefined—and this will override the default prop: microsoft/TypeScript#13195 (comment)
typeProps={foo: string;bar: string}typeInputProps={foo?: string;bar: string;}constdefaultProps: Pick<Props,'foo'>={foo: 'foo'};constinputProps: InputProps={foo: undefined,bar: 'bar'};// Type of `foo` property is `string` but actual value is `undefined`constcompleteProps: Props={ ...defaultProps, ...inputProps};
Ideally, TypeScript would omit an error when trying to pass undefined to an optional prop:
// `{ foo: undefined; bar: string; }` is not assignable to `{ foo?: string; bar: string; }`constinputProps: InputProps={foo: undefined,bar: 'bar'};
In our experience, this has lead the several bugs. The types do not match the values at runtime. A component may receive a prop with a value of undefined, even though undefined is not in that prop's type.
Here is the updated version we've been using. Let me know what you think and if you'd like to update the docs to include these modifications:
importisUndefinedfrom'lodash/isUndefined';importomitByfrom'lodash/omitBy';importReactfrom'react';import{ObjectDiff}from'typelevel-ts';import{getDisplayName}from'HOCs/helpers';exportconstwithDefaults=function<D,AextendsD>(C: React.ComponentType<A>,defaults: D,): React.SFC<ObjectDiff<A,D>>{constdisplayName=`WithDefaults(${getDisplayName(C)})`;constWithDefaults: React.SFC<ObjectDiff<A,D>>=(props)=>{// If a prop is provided with a value of `undefined`, we want the default prop to take// precendence. This ensures the behaviour matches that of React's built-in `defaultProps`// static property on components.constpropsMinusUndefined=omitBy(props,isUndefined);return<C{...defaults}{...propsMinusUndefined}/>;};WithDefaults.displayName=displayName;returnWithDefaults;};
The text was updated successfully, but these errors were encountered:
The documentation suggests a
withDefaults
React HOC. We've been using this in production and we love it, but it has an important issue which I'd like to note for others, and potentially fix with updated docs.TypeScript does not distinguish optional properties (e.g. values either missing or provided with a given type) from
undefined
: microsoft/TypeScript#13195This means that an
undefined
prop may be passed to a component whose prop is marked as optional—notundefined
—and this will override the default prop: microsoft/TypeScript#13195 (comment)Ideally, TypeScript would omit an error when trying to pass
undefined
to an optional prop:In our experience, this has lead the several bugs. The types do not match the values at runtime. A component may receive a prop with a value of
undefined
, even thoughundefined
is not in that prop's type.In the meantime, I think
withDefaults
should allow default props to take precedence over input props when the input props areundefined
(either because they aren't passed through at all, or they were passed through but asundefined
). This matches the behaviour of React's built-indefaultProps
static property on components: https://github.com/facebook/react/blob/373a33f9d30d02cfea814a7803209da6f860a252/packages/react/src/ReactElement.js#L224Here is the updated version we've been using. Let me know what you think and if you'd like to update the docs to include these modifications:
The text was updated successfully, but these errors were encountered: