-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Treating attribute in JSX as literal type #10393
Comments
A quick rundown of problems (or more accurately, reasons this is not a straightforward porting of any existing logic) so we don't forget anything:
We should also consider the effect of |
Also this work should include handling of overloads on SFCs: declare function OneThing({x: string}): JSX.Element;
declare function OneThing({y: number}): JSX.Element;
const c1 = <OneThing x='ok' />
const c2 = <OneThing y={42} />
const c3 = <OneThing x='ok' y={10} /> // not OK, y is extraneous |
I was thinking, is it possible to just desugar the JSX into normal function calls and then let the existing infrastructure handle it? The properties' object type may be passed through a "filter" to remove all aria- and data- props. If you get this machinery working (i.e. the "filtering"), it can also be surfaced as flow does with it's magic functions. |
It isn't, mostly due to spread attributes as noted above. |
I might be missing something very obvious here, but isn't spread a syntactic sugar for Object.assign (if there are literal attributes as well) which we already have a type for? |
I guess Object.assign falls short conveying the "last in wins" semantics / extra attributes bits. |
So if you have something like this interface MyCompProps {
a: string;
b: number;
}
const m = { a: 42, b: 15, c: 20 };
const c = <MyCompProps {...m} a={'ok'} />; You might think "Well, let's just desugar that into..." const c = <MyCompProps a={42} b={15} c={20} a={'ok'} />; But we wouldn't let you write this for three different reasons:
You also might write something like this interface SomeProps {
a?: string;
}
const s: SomeProps = ...;
const c = <MyCompProps a={42} { ...s } />; Where it's still invalid to write |
I was thinking of normal functions. With the jsx flavour, jsx elements get transpiled to React.createElement(comp, props, ...children); What I have in mind is to transform all elements into this representation beforehand and handle it to the normal typechecker. E.g. in the above case, it would be something like the following: function __checkSubtype<T extends U, U>(x: T, y: U): U {
return y;
}
const __tmp = { a: 'ok', d: 3, 'aria-123': 123 };
type __TmpType = $stripAriaAndData(typeof __tmp)
React.createElement(MyCompProps, Object.assign(
__checkSubtype(
null as MyCompProps & Attributes,
__tmp as __TmpType // cast needed to remove aria
),
m as $stripAriaAndData(typeof m)
)); The above is not polished, however the key for me is that F-bound polymorphism can be used for excessiveness checking, a type level function for stripping the aria- and data- properties and Object.assign for sticking together the final result (as does the transpiler). PS: F-Bound polymorphism doesn't properly handle optional properties that are provided. This and data- skipping are currently manifested problems when invoking |
we will have to solve this issue #13526 so the exam will work |
We have take care of this issue when we switch jsx to use overload resolution logic #13640 |
The original issue is issue #10171. Currently we don't treat property assignment of JSX element as literal type as issue #10171 illustrates
One possible solution is to treat property as literal type instead. This could possibly affect how overload will work as well
The text was updated successfully, but these errors were encountered: