Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

Merged
weswigham merged 6 commits intomicrosoft:masterfromweswigham:jsx-namespace-thing
Jun 30, 2018

Conversation

@weswigham
Copy link
Member

@weswighamweswigham commentedMay 25, 2018
edited
Loading

Fixes#23812

Allows, eg:

classComponentextendsReactComponent{staticpropTypes={foo:PropTypes.number,bar:PropTypes.node,baz:PropTypes.string.isRequired,};staticdefaultProps={foo:42,}}consta=<Componentfoo={12}bar="yes"baz="yeah"/>;constb=<Componentfoo={12}/>;// Error, missing required prop barconstc=<Componentbar="yes"baz="yeah"/>;constd=<Componentbar="yes"baz="yo"bat="ohno"/>;// Error, baz not a valid propconste=<Componentfoo={12}bar={null}baz="cool"/>;// bar is nullable/undefinable since it's not marked `isRequired`constf=<Componentfoo={12}bar="yeah"baz={null}/>;// Error, baz is _not_ nullable/undefinable since it's marked `isRequired`

whenJSX.LibraryManagedAttributes<TComponent, TAttributes> is appropriately defined. Thanks to conditional types, this method of supportingpropTypes anddefaultProps allows 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 bothInstrinsicAttributes andInstrinsicClassAttributes using 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? 😄

codepunkt, s-ve, ColCh, krinoid, thetrompf, arusahni, decademoon, pradel, guilhermebruzzi, MOZGIII, and 30 more reacted with thumbs up emojidemensky and franklixuefei reacted with thumbs down emojis-ve, blainekasten, bradleyayers, brieb, mvestergaard, krinoid, thetrompf, arusahni, ladas-larry, AzzkiyOne, and 8 more reacted with hooray emojiColCh, arusahni, ladas-larry, kaoDev, ibezkrovnyi, benjaminRomano, damaon, goldbullet, SergioMorchon, krinoid, and 6 more reacted with heart emoji
@DanielRosenwasser
Copy link
Member

Could you elaborate in this PR on whatLibraryManagedAttributes is intended to do and give some specific implementations examples?

& {[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] : {}};

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

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
Copy link

As background, TS works differently than Flow at the moment with ReactdefaultProps, often causing pain and confusion among junior devs. With this PR,defaultProps will be intuitive. I (think) the ideal behavior is this:

Before

interfaceProps{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

After

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

@weswigham
Copy link
MemberAuthor

weswigham commentedJun 6, 2018
edited
Loading

@jaredpalmer TheProps type parameter should be the "internal" props (so what you read), while the props returned by the type alias should be the "external" props (the ones you write in a tag). So, instead of

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 theProps generic param is the type of the first argument to the factory/class (which includes all defaults).

styfle, sywka, levenleven, piotrwitek, MichalLytek, rozzzly, IllusionMH, kohlmannj, cliedeman, epidemian, and 9 more reacted with thumbs up emoji

@jaredpalmer
Copy link

got it so it will work like Flow. cool!

@Hotell
Copy link

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>;

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
Copy link
MemberAuthor

@mhegazy I've synchronized this branch withmaster; can I get this reviewed?

dsifford, matijagrcic, krinoid, pbeshai, and hahnlee reacted with heart emoji

@mhegazy
Copy link
Contributor

@weswighamweswigham merged commit18e3f48 intomicrosoft:masterJun 30, 2018
@OliverJAsh
Copy link
Contributor

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
Copy link
Contributor

@OliverJAsh this is a different issue i am afraid.

@OliverJAsh
Copy link
Contributor

@mhegazy Is it an issue worth tracking? If so, I'll open a separate issue.

@mhegazy
Copy link
Contributor

yes please.

@weswigham
Copy link
MemberAuthor

@OliverJAsh it's probably also worth noting that while this code is intypescript, there won't be any changes until thereact.d.ts is updated to use the new jsx namespace entrypoint; so until that happensdefaultProps still won't do anything.

@OliverJAsh
Copy link
Contributor

@mhegazy#25503.

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commentedJul 9, 2018
edited
Loading

Locking so users open up new issues instead. That way, we can more easily follow up.

@microsoftmicrosoft locked asresolvedand limited conversation to collaboratorsJul 9, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@DanielRosenwasserDanielRosenwasserDanielRosenwasser left review comments

+3 more reviewers

@jaredpalmerjaredpalmerjaredpalmer left review comments

@ferdaberferdaberferdaber left review comments

@mhegazymhegazymhegazy approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

7 participants

@weswigham@DanielRosenwasser@jaredpalmer@Hotell@mhegazy@OliverJAsh@ferdaber

[8]ページ先頭

©2009-2025 Movatter.jp