Skip to content
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

Enable Typescript to understand JSX default props #1181

Merged
merged 4 commits into from Sep 10, 2018

Conversation

Alexendoo
Copy link
Contributor

This addition allows a Component to use defaultProps without having to declare them as optional, in a nutshell:

Before

class Before extends Component<{ prop?: string }> {
	static defaultProps = {
		prop: "default value"
	};

	render() {
		// this.props.prop is string|undefined
	}
}

const element = <Before />;

After

class After extends Component<{ prop: string }> {
	static defaultProps = {
		prop: "default value"
	};

	render() {
		// typeof this.props.prop is string
	}
}

const element = <After />;

The definition isn't perfect, it doesn't quite understand type unions where the type of a single property changes, e.g.

{ type: "number"; value: number } | { type: "string"; value: string }

But this case doesn't break, it just would require you to still provide a property.

There might be some more things we can do with LibraryManagedAttributes, it could allow the children property to be correct within Components (always an Array) whilst still allowing components to specify the type of children they accept.

See microsoft/TypeScript#24422

This addition allows a Component to use defaultProps without having to
declare them as optional, in a nutshell:

Before

class Before extends Component<{ prop?: string }> {
	static defaultProps = {
		prop: "default value"
	};

	render() {
		// this.props.prop is string|undefined
	}
}

const element = <Before />;

After

class After extends Component<{ prop: string }> {
	static defaultProps = {
		prop: "default value"
	};

	render() {
		// typeof this.props.prop is string
	}
}

const element = <After />;

The definition isn't perfect, it doesn't quite understand type unions where
the type of a single property changes, e.g.

{ type: "number"; value: number } | { type: "string"; value: string }

But this case doesn't break, it just would require you to still provide
a property.

There might be some more things we can do with LibraryManagedAttributes,
it could allow the children property to be correct within Components
(always an Array) whilst still allowing components to specify the type
of children they accept.
@coveralls
Copy link

coveralls commented Aug 10, 2018

Coverage Status

Coverage remained the same at 100.0% when pulling d1974c7 on Alexendoo:typed-defaultProps into 62c04e0 on developit:master.

@developit
Copy link
Member

Ahhh yes, I totally wished for this yesterday! Good timing, thanks @Alexendoo :)

@developit
Copy link
Member

I'm guessing this requires TS 3+? Might be worth putting this into 9.0 if so.

@Alexendoo
Copy link
Contributor Author

Yep the feature requires 3.0 to receive the benefits of it, on 2.8/2.9 it provides no improvements, for them it is just an extra type on JSX that it doesn't use so nothing changes.

However it is a breaking change, it requires TS >= 2.8 because of the conditional types, even if they aren't used they are still present in the declaration file. I don't know what the minimum version of
typescript preact currently requires but I expect it to be below 2.8, I would guess 2.3 (generic defaults) from looking at the file.

@developit
Copy link
Member

@marvinhagemeister might know what we currently require. For some reason I feel like I remember adding a 2.8-specific feature?

@marvinhagemeister
Copy link
Member

@developit I thought too that we had something specifically added with TS 2.8 but looking at the types again we don't have added any breaking change yet. The one with type checking children is simply ignored on older TS version because it's just an interface.

With this PR we need to update our TS version requirements to at least 2.8 and better 3.0. I'm totally fine with this as I upgraded multiple major code bases to 3.0 without any issues at all.

The CI failure seems strange. Looks like npm install doesn't finish correctly.

Copy link
Member

@marvinhagemeister marvinhagemeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for another great PR 🎉

@developit
Copy link
Member

developit commented Aug 22, 2018

CI had only failed on one of the node versions, which means it's a fluke.

Should we wait a bit before jumping to TS 3.0? It only came out 2 weeks ago right?

@Alexendoo
Copy link
Contributor Author

I think it should be fine since it won't break on 2.8 and 2.9

Plus the 3.0 release isn't as scary as it sounds, I think 2.9 -> 3.0 is just how they wanted to do version numbering, TS doesn't use semver since most releases are breaking changes in a type system. It actually has pretty few breaking changes so it should be an easy update for most

@marvinhagemeister
Copy link
Member

Would love to merge this, but the CI is giving me trouble. Not sure why node8 fails to install the proper dependencies.

@Alexendoo
Copy link
Contributor Author

node_modules is set to be cached, maybe it's an issue with the cache it's pulling in each time?

@Alexendoo
Copy link
Contributor Author

Could be worth giving this a shot @marvinhagemeister https://docs.travis-ci.com/user/caching/#clearing-caches

@marvinhagemeister
Copy link
Member

@Alexendoo You're right, that fixes it 🎉

@marvinhagemeister marvinhagemeister merged commit b5c4a36 into preactjs:master Sep 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants