Skip to content

TypeScript support using Babel 7#4837

Merged
Timer merged 1 commit intofacebook:masterfrom
brunolemos:next-typescript
Oct 21, 2018
Merged

TypeScript support using Babel 7#4837
Timer merged 1 commit intofacebook:masterfrom
brunolemos:next-typescript

Conversation

@brunolemos
Copy link
Copy Markdown
Contributor

@brunolemos brunolemos commented Jul 29, 2018

Adds TypeScript support.

Closes #4146
Closes #2815

The user can just rename .js to .tsx and it will work.

To enable type checking, the user needs to create a tsconfig.json file at the root directory and install the typescript fork-ts-checker-webpack-plugin dependencies. It will appear at the same console as the build one. Another option is to install only typescript and run npx tsc -w on a new terminal tab instead.

Includes

  • Support .ts and .tsx file extensions
  • Support type checking using fork-ts-checker-webpack-plugin (opt in)
  • Support media imports json, bmp, gif, jpeg, jpg, png and svg
  • Support typescript option on react-app babel preset to enable/disable @babel/preset-typescript (enabled by default, just like flow)
  • Update docs
  • Basic test

These items were included, but removed per review suggestion

Pending suggestions (help wanted!)

  • Fix build test not passing even though it's correct (Tests are using code from npm instead of code from pull request #5440)
  • Add more advanced tests
  • Use async: true on type checking? (would need to fix errors not showing up) (it's ok for this first iteration)
  • Make sure ESLint works great on tsx files
  • Make sure there are no conflicts between typescript preset and flow plugin because both are being enabled together by default (none were found or reported by now)
  • Automatically generate a tsconfig.json when typescript is imported for the first time?
  • Check and force some tsconfig.json options like isolatedModules: true?
  • Remove typescript dependency? (will probably need to change something on fork-ts-checker-webpack-plugin, because it isn't working without it)
  • Re-run type checking after changing files that webpack is not watching? (TypeScript support using Babel 7 #4837 (comment))
  • Enable type checking on test files using ts-jest? (TypeScript support using Babel 7 #4837 (comment)) (no)

Screenshot

type TestType = 'a' | 'b'
const x: TestType = 123

image

How to try this PR while it's not merged

  • Clone
    • git clone git@github.com:brunolemos/create-react-app.git
    • cd create-react-app
    • git checkout next-typescript
  • Compile
    • yarn
  • Create Link
    • cd packages/react-scripts/
    • yarn link
  • Create New Project
    • cd ~/your/projects/folder
    • npx create-react-app app-name
    • cd app-name
  • Use Link
    • yarn link react-scripts
  • Setup TypeScript
  • Finish
    • yarn start
    • Have fun with types 🎉

@ianschmitz
Copy link
Copy Markdown
Contributor

One way to fix image imports TS error:

https://github.com/wmonk/create-react-app-typescript/blob/e4b1f9424fa14f7aae7f0cbf5fd64e18dd273527/packages/react-scripts/template/images.d.ts

However this doesn't take into account the recent improvements made in CRA 2.0 such as #3718

@brunolemos
Copy link
Copy Markdown
Contributor Author

brunolemos commented Jul 30, 2018

@iainbeeston thanks! I added an index.d.ts file fixing jpg, png and svg.
It also includes typings for the svg ReactComponent.

We currently only have one template folder so this way the index.d.ts will be available on non-typescript projects as well, not sure if that's a problem. Maybe it's a good thing, because it adds autocomplete to js projects as well.

@brunolemos brunolemos force-pushed the next-typescript branch 6 times, most recently from 9f3e2c2 to 0db667c Compare August 9, 2018 06:50
@brunolemos brunolemos force-pushed the next-typescript branch 10 times, most recently from 06d8ef5 to f33e0ca Compare August 10, 2018 10:10
@@ -0,0 +1,12 @@
declare module '*.jpg'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't think this file should be called index.d.ts as this name will conflict with the automatically generated typings file for index.ts. In my projects I normally call this file externals.d.ts or similar but I don't really mind what it is called.

declare module '*.png'

declare module '*.svg' {
import * as React from 'react'
Copy link
Copy Markdown

@frankwallis frankwallis Aug 13, 2018

Choose a reason for hiding this comment

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

To be consistent with index.js this should be import React from 'react'. This does assume that esModuleInterop: true is specified in tsconfig.json but I think this is best practice for new projects as it means that typescript and babel are more closely aligned.

declare module '*.svg' {
import * as React from 'react'

export const ReactComponent: React.SFC<React.SVGProps<SVGSVGElement>>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm interested to know why this is needed?

@@ -1,5 +1,7 @@
import 'jest';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

An alternative to adding this import is to add types: [ 'jest' ] to tsconfig.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't believe either should be needed. Typescript should pick up the node_modules/@types definitions automatically without any extra effort.

```json
{
"compilerOptions": {
"target": "ESNEXT",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: capitalization

@Jessidhia
Copy link
Copy Markdown

Jessidhia commented Oct 16, 2018

enums do work with babel, you just can't declare the same enum multiple times in the same scope. With tsc, those two enums would get merged, but with babel, they're new declarations and one would override the other.

const enums can't be supported because const enums only exist as a type.

@GeeWee
Copy link
Copy Markdown

GeeWee commented Oct 16, 2018

Just throwing in my two cents as a ts-jest maintainer:

Most of the features Babel doesn't support aren't very widely used (we didn't support them for a long time and got very few issues)

If you decide to use ts-jest for testing you'll:
A) gain access to some test fee helpers that e.g. creates types for mocked objects
B) Get the "real" ts experience (we run a full language server)
C) An inconsistent experience. You face the potential of something working in tests but not when launching the app. (Though this can be mitigated by some ts-jest options)

I'd probably just use Babel

@DanielRosenwasser
Copy link
Copy Markdown

DanielRosenwasser commented Oct 16, 2018

TypeScript PM here. Broadly speaking, I feel that

  • namespaces are not a huge loss; the React community is firmly on-board with ES modules anyway, and that's the direction the TypeScript world is taking.
  • const enums are often misused. Sure, they can be great for the internals of a library to get some speed improvements, but they generally shouldn't be used outside of that scope.
  • Merging behavior is marginally useful now that TypeScript 3.1 has the ability to tack properties onto functions. The fact that enums merge is also something I've never seen used out in the wild.

Anyway, @RyanCavanaugh might have some thoughts here too.

@jleck
Copy link
Copy Markdown

jleck commented Oct 16, 2018

Hi all,

I was looking moving over to this from react-scripts-ts, but I have an issue around paths. In my tsconfig I have the following:

"compilerOptions": {
        ...
        "paths": {
            "@components/*": ["components/*", "core/src/components/*"],
        }
},

I.E. aliases with multiple paths. Unfortunately babel-plugin-module-resolver doesn't seem to support arrays as aliases, so I can't get my project working.

Not a showstopper for most people, but could cause some issues.

@afarmerdev
Copy link
Copy Markdown

  • namespaces are not a huge loss; the React community is firmly on-board with ES modules anyway, and that's the direction the TypeScript world is taking.

@DanielRosenwasser do we still have "global namespace" where types added automatically from definition-only files? So we don't need to "virtual import" those types everywhere.

@DanielRosenwasser
Copy link
Copy Markdown

@Serguzest can you give an example of what scenario you have in mind here?

@afarmerdev
Copy link
Copy Markdown

afarmerdev commented Oct 19, 2018

@Serguzest can you give an example of what scenario you have in mind here?

@DanielRosenwasser

src/models.ts

interface user {
  name: string;
}

src/someDirectory/someOtherFile.tsx

import * as React from "react";

//I don't need to explicitly import "user" type to able to use it in here
const user: user = {
  name: "ahmet"
};

@samuelcastro
Copy link
Copy Markdown

Any thoughts when are we going to get this through?

@samuelcastro
Copy link
Copy Markdown

samuelcastro commented Oct 19, 2018

@brunolemos I saw that these items were removed:

  • TSLint support using fork-ts-checker-webpack-plugin
  • ESLint support for TypeScript files using typescript-eslint-parser

Any reasons why? Which one should we use, would tslint make more sense since it's typescript? And last, how to use it with tslint?

@brunolemos
Copy link
Copy Markdown
Contributor Author

brunolemos commented Oct 20, 2018

@samuelcastro: I saw that these items were removed, any reasons why?

TL/DR, ESLint was not enabled on ts files because it requires typescript-eslint-parser which is still not mature and has a big Help Wanted! banner in the readme, which could cause maintainability issues for the CRA team. It also targets specific versions of typescript which could prevent users from upgrading. (#4837 (comment), #4837 (comment))

TSLint built-in support was removed because CRA itself does not lint style preferences, but only critical things like undeclared variable names and typescript already has good defaults for this. Also, the user can run tslint on their own with no problem. (#4837 (comment))

@stunaz
Copy link
Copy Markdown

stunaz commented Oct 20, 2018

Great! Now what? Release, shall we?

Comment thread packages/react-scripts/scripts/utils/createJestConfig.js
@alexdor
Copy link
Copy Markdown

alexdor commented Oct 21, 2018

Huge thanks to @brunolemos for all his effort and of course huge thanks to the team of create react app : ) Can't wait for this to be released : )

@brunolemos
Copy link
Copy Markdown
Contributor Author

brunolemos commented Oct 21, 2018

IT'S MERGED 🎉🎉🎉
Thanks everyone for the motivation and reviews, and thanks @Timer for merging!

EDIT: Just tweeted about it

💙

@RIP21
Copy link
Copy Markdown

RIP21 commented Oct 21, 2018

Amazing stuff! :) Finally :)

@nucab
Copy link
Copy Markdown

nucab commented Oct 22, 2018

Many thanks to @brunolemos for your efforts.. Looking forward for the release :)

@johnnyreilly
Copy link
Copy Markdown
Contributor

I'm so happy this has merged!

A future improvement could be strongly typed JSON support by setting this option in tsconfig.json:

	"resolveJsonModule": true

@veeral-patel
Copy link
Copy Markdown

Awesome. Thank you!

@Timer
Copy link
Copy Markdown
Contributor

Timer commented Oct 23, 2018

I've locked this PR since it's high profile and to keep notification spam low. We'll post updates here when we have them.

Please file any concerns as new issues, thanks!

@Timer
Copy link
Copy Markdown
Contributor

Timer commented Oct 30, 2018

TypeScript is now officially supported as of Create React App 2.1. Read the release notes to get started!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFC: Zero-config TypeScript with Babel 7