TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Incorrectly merging JSX.IntrinsicElements with other properties / JSX issue?

Open alesmenzel opened this issue 3 years ago • 0 comments

Bug Report

🔎 Search Terms

intersection, merge types, react intrinsic type

🕗 Version & Regression Information

  • This is a crash - No
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about intersection, merge types, react intrinsic type

⏯ Playground Link

Playground link with relevant code

💻 Code

function SomeComponent<T extends 'button' | 'a'>(props: { element?: T } & JSX.IntrinsicElements[T]): JSX.Element {
    // Just so the return value is RectElement, the rendered element doesnt matter
    return <div />
}

function Test<T extends 'button' | 'a'>(el: T) {
    // ✅
	// return <SomeComponent element={el} className='yolo' />

    // ✅
    // return <SomeComponent element={el}>{null}</SomeComponent>

    // ❌ Type '{ element: T; }' is not assignable to type 'IntrinsicElements[T]'.
    // TS here completely ignores the props type "{ element?: T } & JSX.IntrinsicElements[T]" where I specify the element key?
    return <SomeComponent element={el} />
}

🙁 Actual behavior

I am getting Type '{ element: T; }' is not assignable to type 'IntrinsicElements[T]'. error even-though my type is specified as intersection of { element?: T } & JSX.IntrinsicElements[T]. I have checked and there is no element key in the IntrinsicElements - I can prove that by using Omit<JSX.IntrinsicElements[T], 'element'>, which still returns error. Also when extracting the type into a separate type like this

type TEST = { element?: 'button' | 'a' } & JSX.IntrinsicElements['button' | 'a']
type TEST_ELEMENT = TEST['element']
// ✅          ^^ "button" | "a" | undefined

it returns the expected type of element

🙂 Expected behavior

I expect there is no error and that Type '{ element: T; }' is ASSIGNABLE to type '{ element: T; } & IntrinsicElements[T]'..

alesmenzel avatar Aug 04 '22 09:08 alesmenzel