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
When an object is spreaded like const { type, foo, bar, ...rest } = props: A | B | C, all properties keep the same context (= relation to props object type - A | B | C). So, whenever you would narrow based on any of the discriminating type, it would narrow other properties (foo, bar, ...rest). It would simplify working with JSX where it matters when extra properties are passed to the underlying element, because the prop doesn't have to be supported by the DOM and you would get a warning.
π Motivating Example
See below.
π» Use Cases
See playground above, it is very common to have a discriminated union as some form of input and then pass only the rest of the object down to some handler, omitting the discriminator as it is no longer needed. In most cases, it is fine to pass extra property, but when used with JSX, it adds extra property that will be added to the DOM.
typeAvatarProps={type: 'image',src: string,className: string}|{type: 'initials',name: string,className: string}constAvatar=({ type, className, ...rest}: AvatarProps)=>{if(type==='image'){return<ImageAvatarclassName={cx("avatar",className)}{...rest}/>// We don't want to pass type here as it is not part of the ImageAvatar interface}if(type==='initials'){return<InitialsAvatarclassName={cx("avatar",className)}{...rest}/>}thrownewError(...)}
The current workaround is to use the whole props object instead and then omit the unwanted props
typeAvatarProps={type: 'image',src: string}|{type: 'initials',name: string}constAvatar=(props: AvatarProps)=>{if(props.type==='image'){const{ className, ...rest}=propsreturn<ImageAvatarclassName={cx("avatar",className)}{..._omit(rest,"type")}/>// We don't want to pass type here as it is not part of the ImageAvatar interface}if(props.type==='initials'){const{ className, ...rest}=propsreturn<InitialsAvatarclassName={cx("avatar",className)}{..._omit(rest,"type")}/>}thrownewError(...)}
As you can see the DX could be nicer if the "context" that ...rest belongs to the same object as typeand thus discriminating on type should make the ...rest return the correct type.
The text was updated successfully, but these errors were encountered:
Suggestion
See playground, it would be really nice if TS count keep the discriminator in context for other properties coming from the same object.
π Search Terms
Spread, context, discriminating union
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
When an object is spreaded like
const { type, foo, bar, ...rest } = props: A | B | C
, all properties keep the same context (= relation toprops
object type -A | B | C
). So, whenever you would narrow based on any of the discriminating type, it would narrow other properties (foo
,bar
,...rest
). It would simplify working with JSX where it matters when extra properties are passed to the underlying element, because the prop doesn't have to be supported by the DOM and you would get a warning.π Motivating Example
See below.
π» Use Cases
See playground above, it is very common to have a discriminated union as some form of input and then pass only the rest of the object down to some handler, omitting the discriminator as it is no longer needed. In most cases, it is fine to pass extra property, but when used with JSX, it adds extra property that will be added to the DOM.
The current workaround is to use the whole props object instead and then omit the unwanted props
As you can see the DX could be nicer if the "context" that
...rest
belongs to the same object astype
and thus discriminating on type should make the...rest
return the correct type.The text was updated successfully, but these errors were encountered: