Fix issues spreading omitted props onto components (#3313)

* Simplify props types

wip

wip

* Remove unused types

* Remove test

it’s no longer relevant

* Update changelog
This commit is contained in:
Jordan Pittman
2024-06-24 14:00:57 -04:00
committed by GitHub
parent d60ed6a670
commit a593d19955
5 changed files with 16 additions and 39 deletions
+3 -1
View File
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Nothing yet!
### Fixed
- Fix issues spreading omitted props onto components ([#3313](https://github.com/tailwindlabs/headlessui/pull/3313))
## [2.1.0] - 2024-06-21
@@ -318,7 +318,6 @@ function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_
leaveFrom,
leaveTo,
// @ts-expect-error
...theirProps
} = props as typeof props
let container = useRef<HTMLElement | null>(null)
@@ -444,6 +443,8 @@ function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_
className:
classNames(
// Incoming classes if any
// @ts-expect-error: className may not exist because not
// all components accept className (but all HTML elements do)
theirProps.className,
// Apply these classes immediately
@@ -498,7 +499,6 @@ function TransitionRootFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_C
props: TransitionRootProps<TTag>,
ref: Ref<HTMLElement>
) {
// @ts-expect-error
let { show, appear = false, unmount = true, ...theirProps } = props as typeof props
let internalTransitionRef = useRef<HTMLElement | null>(null)
let requiresRef = shouldForwardRef(props)
@@ -610,10 +610,8 @@ function ChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG>
return (
<>
{!hasTransitionContext && hasOpenClosedContext ? (
// @ts-expect-error This is an object
<TransitionRoot ref={ref} {...props} />
) : (
// @ts-expect-error This is an object
<InternalTransitionChild ref={ref} {...props} />
)}
</>
-17
View File
@@ -2,12 +2,6 @@ import type { JSXElementConstructor, ReactElement, ReactNode } from 'react'
export type ReactTag = keyof JSX.IntrinsicElements | JSXElementConstructor<any>
// A unique placeholder we can use as a default. This is nice because we can use this instead of
// defaulting to null / never / ... and possibly collide with actual data.
// Ideally we use a unique symbol here.
let __ = '1D45E01E-AF44-47C4-988A-19A94EBAF55C' as const
export type __ = typeof __
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
export type PropsOf<TTag extends ReactTag> = TTag extends React.ElementType
@@ -55,15 +49,4 @@ export type Props<
ClassNameOverride<TTag, TSlot> &
Overrides
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }
export type XOR<T, U> = T | U extends __
? never
: T extends __
? U
: U extends __
? T
: T | U extends object
? (Without<T, U> & U) | (Without<U, T> & T)
: T | U
export type EnsureArray<T> = T extends any[] ? T : Expand<T>[]
@@ -423,16 +423,6 @@ describe('Features.Static | Features.RenderStrategy', () => {
)
}
// TODO: Can we "legit" test this? 🤔
it('should result in a typescript error', () => {
testRender(
// @ts-expect-error static & unmount together are incompatible
<Dummy show={false} static unmount>
Contents
</Dummy>
)
})
// To avoid duplication, and to make sure that the features tested in isolation can also be
// re-used when they are combined.
testStaticFeature(Dummy)
+11 -7
View File
@@ -11,7 +11,7 @@ import {
type ReactElement,
type Ref,
} from 'react'
import type { Expand, Props, XOR, __ } from '../types'
import type { Expand, Props } from '../types'
import { classNames } from './class-names'
import { match } from './match'
@@ -40,17 +40,21 @@ export enum RenderStrategy {
Hidden,
}
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any
? R
: never
type PropsForFeature<
TPassedInFeatures extends RenderFeatures,
TForFeature extends RenderFeatures,
TProps,
> = {
[P in TPassedInFeatures]: P extends TForFeature ? TProps : __
}[TPassedInFeatures]
> = TPassedInFeatures extends TForFeature ? TProps : {}
export type PropsForFeatures<T extends RenderFeatures> = XOR<
PropsForFeature<T, RenderFeatures.Static, { static?: boolean }>,
PropsForFeature<T, RenderFeatures.RenderStrategy, { unmount?: boolean }>
export type PropsForFeatures<T extends RenderFeatures> = Expand<
UnionToIntersection<
| PropsForFeature<T, RenderFeatures.Static, { static?: boolean }>
| PropsForFeature<T, RenderFeatures.RenderStrategy, { unmount?: boolean }>
>
>
export function render<TFeature extends RenderFeatures, TTag extends ElementType, TSlot>({