- Notifications
You must be signed in to change notification settings - Fork13.2k
Support LibraryManagedAttributes<TComponent, TAttributes> JSX namespace type#24422
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
DanielRosenwasser commentedMay 31, 2018
Could you elaborate in this PR on what |
| & {[K in Exclude<keyof TProps, keyof TDefaults>]: TProps[K]} | ||
| & Partial<TDefaults>; | ||
| type InferedPropTypes<P> = {[K in keyof P]: P[K] extends PropTypeChecker<infer T, infer U> ? PropTypeChecker<T, U>[typeof checkedType] : {}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I know it's just a test, butInferedPropTypes ->InferredPropTypes
| const x = <JustDefaultPropsWithSpecifiedGeneric foo="eh" />; | ||
| const y = <JustDefaultPropsWithSpecifiedGeneric foo="no" bar="ok" />; // error, no prop named bar | ||
| const z = <JustDefaultPropsWithSpecifiedGeneric foo={12} />; // error, wrong type | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
What about<JustDefaultPropsWithSpecifiedGeneric />? Is that kosher?
jaredpalmer commentedJun 6, 2018
As background, TS works differently than Flow at the moment with React BeforeinterfaceProps{thing?:string;// thing is optional, but it is always defined because it has a default prop.}classThingextendsReact.Component<Props>{staticdefaultProps={thing:'hello'}render(){console.log(this.props.thing!.length)// forced with !// ...}}// ..<Thing/>// this works AfterinterfaceProps{thing?:string;// still optional}classThingextendsReact.Component<Props>{staticdefaultProps={thing:'hello'}render(){console.log(this.props.thing)// inferred because of defaultProps, no ! needed// ...}}// ..<Thing/>// works |
weswigham commentedJun 6, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@jaredpalmer The interfaceProps{thing?:string;// still optional}classThingextendsReact.Component<Props>{staticdefaultProps={thing:'hello'}render(){console.log(this.props.thing)// inferred because of defaultProps, no ! needed// ...}}// ..<Thing/>//works you'd have interfaceProps{thing:string;// note: not optional within class, but is optional when writing due to the default}classThingextendsReact.Component<Props>{staticdefaultProps={thing:'hello'}render(){console.log(this.props.thing)// strict type from `Props`// ...}}// ..<Thing/>// works, thanks to `defaultProps` or at least that's what makes sense to me - since the |
jaredpalmer commentedJun 6, 2018
got it so it will work like Flow. cool! |
Hotell commentedJun 6, 2018
This is indeed awesome! In the meantime I wrote an article for React consumers struggling with this "deal breaker" ✌️https://medium.com/@martin_hotell/react-typescript-and-defaultprops-dilemma-ca7f81c661c7 |
| type Defaultize<TProps, TDefaults> = | ||
| & {[K in Extract<keyof TProps, keyof TDefaults>]?: TProps[K]} | ||
| & {[K in Exclude<keyof TProps, keyof TDefaults>]: TProps[K]} | ||
| & Partial<TDefaults>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Why is thePartial<TDefaults> here intersected with the extracted mapped type fromTDefaults? What kind of error does that produce iftypeof TProps[K] is incompatible withtypeof TDefaults[K]?
weswigham commentedJun 30, 2018
@mhegazy I've synchronized this branch with |
mhegazy commentedJun 30, 2018
We will need to updatehttps://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/JSX.md |
OliverJAsh commentedJul 6, 2018
What is the expected behaviour when the props type is a union? Is this expected? {typeProps={shared:string}&(|{type:'foo';foo:string;}|{type:'bar';bar:string;});classComponentextendsReactComponent<Props>{staticdefaultProps={shared:'yay',};}<Componenttype="foo"/>;// Expected error, got none// Unexpected error// Property 'foo' does not exist on type 'Defaultize<Props, { shared: string; }>'.<Componenttype="foo"foo="1"/>;} |
mhegazy commentedJul 6, 2018
@OliverJAsh this is a different issue i am afraid. |
OliverJAsh commentedJul 6, 2018
@mhegazy Is it an issue worth tracking? If so, I'll open a separate issue. |
mhegazy commentedJul 6, 2018
yes please. |
weswigham commentedJul 6, 2018
@OliverJAsh it's probably also worth noting that while this code is in |
OliverJAsh commentedJul 8, 2018
DanielRosenwasser commentedJul 9, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Locking so users open up new issues instead. That way, we can more easily follow up. |
Uh oh!
There was an error while loading.Please reload this page.
Fixes#23812
Allows, eg:
when
JSX.LibraryManagedAttributes<TComponent, TAttributes>is appropriately defined. Thanks to conditional types, this method of supportingpropTypesanddefaultPropsallows definition authors a ton of freedom in how the static types need to be transformed before they are checked against what the user wrote. (Allowing customization of, for example: how conflicts between provided props and inferred props are handled, how inferences are mapped, how optionality is handled, and how inferences from differing places should be combined)As an aside, you can fully implement the functionality of both
InstrinsicAttributesandInstrinsicClassAttributesusing this new type entrypoint, so in a way it obsoletes them.Feel free to 🚲 🏠 with the name and give feedback; the actual implementation is relatively simple.@DanielRosenwasser you probably have some opinions here, right? 😄