-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
Bug Report
I have difficulty naming the issue, please suggest/make changes to the title/search terms.
🔎 Search Terms
Function, JSX, inferring, generic, difference, inference priority
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about n/a
⏯ Playground Link
Playground link with relevant code
💻 Code
import React from "react";
type TranslationEntry = {
args: [] | [unknown];
}
type Translations = {
a: { args: [string] },
b: { args: [] }
}
// Relation:
// Translations satisfies Record<string, TranslationEntry>
// If the selected translation entry requires arguments, intersect with object that requires 'args'
type TProps<Entry extends TranslationEntry> = {
getTranslationEntry: (allTranslations: Translations) => Entry,
} & (Entry["args"] extends [unknown] ? {
args: Entry["args"][0]
} : {});
declare function T<Entry extends TranslationEntry>(
props: TProps<Entry>
): JSX.Element;
// Calling the function directly works
T({
getTranslationEntry: (allTranslations) => allTranslations.a,
args: "a"
});
// But the JSX version, however, doesn't
<T
getTranslationEntry={(allTranslations) => allTranslations.a}
args="a"
// ^^^^ Property 'args' does not exist on type 'IntrinsicAttributes & { getTranslationEntry: (allTranslations: Translations) => TranslationEntry; }'
/>To add some context to above code
<T /> is a component that uses the form <T getTranslationEntry={ t => t.xyz } /> to specify which translation (entry) to display. Depending on what's selected, additional arguments are required.
In order to be able to omit the args prop when not required, the intersection with
(Entry["args"] extends [unknown] ? {
args: Entry["args"][0]
} : {})does this.
🙂 Expected behavior
As it does for the function call, for the JSX element should infer it's generic parameter E to { args: [string] }. Because of this, Entry["args"] extends [unknown] ? ... : { } then correctly resolves to { args: string }
🙁 Actual behavior
Entry["args"] extends [unknown] ? ... : { } resolves to { } instead, but strangely only for the JSX variant.
💡 Other
What is most confusing is the following seeming contradiction:
<T
// ^Property 'args' is missing in type '{ getTranslationEntry: (allTranslations: Translations) => { args: [string]; }; }' but required in type '{ args: string; }'.
getTranslationEntry={(allTranslations) => allTranslations.a}
/>;
<T
getTranslationEntry={(allTranslations) => allTranslations.a}
args="a"
// ^^^^ Property 'args' does not exist on type 'IntrinsicAttributes & { getTranslationEntry: (allTranslations: Translations) => TranslationEntry; }'.
/>;