Tìm kiếm trang web

Xung đột giữa TypeScript và flow khi test một component react-native


Tôi có một boilerplate react-native đơn giản và tôi đang cố gắng thử nghiệm một component react-native đơn giản được viết bằng typescript:

// Splash.tsx
import React, { Component } from 'react';
import { SContainer, STitle, SSubtitle, SPara } from './Splash.style';

export default class Splash extends Component {
  render() {
    return (
      <SContainer>
        <STitle>Clean Slate</STitle>
        <SSubtitle>A react-native boilerplate</SSubtitle>
        <SPara>
          with TypeScript, React-Navigation, {'\n'}styled-components, Redux and
          Sagas
        </SPara>
      </SContainer>
    );
  }
}

SContainer, STitle, SSubtitle & SPara là styled-components

Và tôi có bài kiểm tra này:

// Splash.spec.tsx
import React from 'react';
import Splash from './Splash';
import renderer from 'react-test-renderer';

test('renders correctly', () => {
  const tree = renderer.create(<Splash onAppStart={() => {}} />).toJSON();
  expect(tree).toMatchSnapshot();
});

Tôi có các bài kiểm tra jest khác của các hàm JS/TS thuần túy (không có JSX) và các bài kiểm tra chạy và vượt qua hoàn hảo. Nhưng khi tôi chạy jest -- -u trên Splash.spec.tsx, tôi nhận được điều này:

 FAIL  src/screens/Splash/Splash.spec.tsx
  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:18:1 - error TS8002: 'import ... =' can only be used in a .ts file.

    18 import type {
       ~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:41:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    41 export type ViewStyleProp = ____ViewStyleProp_Internal;
                   ~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:51:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    51 export type TextStyleProp = ____TextStyleProp_Internal;
                   ~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:61:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    61 export type ImageStyleProp = ____ImageStyleProp_Internal;
                   ~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:70:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    70 export type DangerouslyImpreciseStyleProp = ____DangerouslyImpreciseStyleProp_Internal;
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:88:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    88 export type TypeForStyleKey<
                   ~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:90:18 - error TS8011: 'type arguments' can only be used in a .ts file.

    90 > = $ElementType<____DangerouslyImpreciseStyle_Internal, key>;
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:107:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    107 export type ViewStyle = ____ViewStyle_Internal;
                    ~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:124:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    124 export type TextStyle = ____TextStyle_Internal;
                    ~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:141:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    141 export type ImageStyle = ____ImageStyle_Internal;
                    ~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:155:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    155 export type DangerouslyImpreciseStyle = ____DangerouslyImpreciseStyle_Internal;
                    ~~~~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:162:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    162 export type LayoutStyle = ____LayoutStyle_Internal;
                    ~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:163:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    163 export type ShadowStyle = ____ShadowStyle_Internal;
                    ~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:164:13 - error TS8008: 'type aliases' can only be used in a .ts file.

    164 export type TransformStyle = ____TransformStyle_Internal;
                    ~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:171:21 - error TS8010: 'types' can only be used in a .ts file.

    171 const absoluteFill: LayoutStyle = {
                            ~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:253:32 - error TS8010: 'types' can only be used in a .ts file.

    253   absoluteFill: (absoluteFill: any), // TODO: This should be updated after we fix downstream Flow sites.
                                       ~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:275:11 - error TS8004: 'type parameter declarations' can only be used in a .ts file.

    275   compose<T: DangerouslyImpreciseStyleProp>(
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:276:13 - error TS8010: 'types' can only be used in a .ts file.

    276     style1: ?T,
                    ~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:277:13 - error TS8010: 'types' can only be used in a .ts file.

    277     style2: ?T,
                    ~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:278:6 - error TS8010: 'types' can only be used in a .ts file.

    278   ): ?T | $ReadOnlyArray<T> {
             ~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:280:48 - error TS8011: 'type arguments' can only be used in a .ts file.

    280       return ([style1, style2]: $ReadOnlyArray<T>);
                                                       ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:337:15 - error TS8010: 'types' can only be used in a .ts file.

    337     property: string,
                      ~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:338:14 - error TS8010: 'types' can only be used in a .ts file.

    338     process: (nextProp: mixed) => mixed,
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:10 - error TS8004: 'type parameter declarations' can only be used in a .ts file.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {

    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:18:13 - error TS1005: '=' expected.

    18 import type {
                   ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:31:1 - error TS1109: Expression expected.

    31 } from 'StyleSheetTypes';
       ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:31:8 - error TS1005: ';' expected.

    31 } from 'StyleSheetTypes';
              ~~~~~~~~~~~~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:89:3 - error TS1139: Type parameter declaration expected.

    89   +key: $Keys<____DangerouslyImpreciseStyle_Internal>,
         ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:89:7 - error TS1005: ';' expected.

    89   +key: $Keys<____DangerouslyImpreciseStyle_Internal>,
             ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:89:54 - error TS1109: Expression expected.

    89   +key: $Keys<____DangerouslyImpreciseStyle_Internal>,
                                                            ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:90:1 - error TS1109: Expression expected.

    90 > = $ElementType<____DangerouslyImpreciseStyle_Internal, key>;
       ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:90:3 - error TS1109: Expression expected.

    90 > = $ElementType<____DangerouslyImpreciseStyle_Internal, key>;
         ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:90:62 - error TS1005: '(' expected.

    90 > = $ElementType<____DangerouslyImpreciseStyle_Internal, key>;
                                                                    ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:253:36 - error TS1005: '=>' expected.

    253   absoluteFill: (absoluteFill: any), // TODO: This should be updated after we fix downstream Flow sites.
                                           ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:275:12 - error TS1005: ',' expected.

    275   compose<T: DangerouslyImpreciseStyleProp>(
                   ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:280:31 - error TS1005: ')' expected.

    280       return ([style1, style2]: $ReadOnlyArray<T>);
                                      ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:280:50 - error TS1005: '(' expected.

    280       return ([style1, style2]: $ReadOnlyArray<T>);
                                                         ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:10 - error TS1139: Type parameter declaration expected.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
                 ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:12 - error TS1005: ';' expected.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
                   ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:38 - error TS1005: ')' expected.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
                                             ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:41 - error TS1005: ';' expected.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
                                                ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:361:42 - error TS1128: Declaration or statement expected.

    361   create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
                                                 ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:373:5 - error TS1005: ',' expected.

    373     return obj;
            ~~~~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:373:12 - error TS1005: ':' expected.

    373     return obj;
                   ~~~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:373:15 - error TS1005: ',' expected.

    373     return obj;
                      ~
    node_modules/react-native/Libraries/StyleSheet/StyleSheet.js:375:1 - error TS1109: Expression expected.

    375 };
        ~

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    95.24 |    71.43 |      100 |    94.44 |                   |
 actions   |      100 |      100 |      100 |      100 |                   |
  index.ts |      100 |      100 |      100 |      100 |                   |
 reducers  |    92.31 |    71.43 |      100 |    92.31 |                   |
  index.ts |    92.31 |    71.43 |      100 |    92.31 |                34 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 failed, 2 passed, 3 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        4.247s
Ran all test suites matching /src/i.

Active Filters: filename /src/
 › Press c to clear filters.

Watch Usage
 › Press a to run all tests.
 › Press f to run only failed tests.
 › Press o to only run tests related to changed files.
 › Press q to quit watch mode.
 › Press t to filter by a test name regex pattern.
 › Press p to filter by a filename regex pattern.
 › Press Enter to trigger a test run.

Phần jest trong file package.json của tôi trông như sau:

  "jest": {
    "preset": "react-native",
    "verbose": true,
    "clearMocks": true,
    "collectCoverage": true,
    "globals": {
      "__DEV__": true
    },
    "transform": {
      "^.+\\.(t|j)sx?$": "ts-jest"
    },
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ],
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "testMatch": [
      "**/**/*.(test|spec).(tsx|ts|js)"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(react-native|jest-styled-components|styled-components)/)"
    ],
    "testEnvironment": "node"
  }

Vậy tôi thấy các lỗi xuất phát từ thư viện flow typed react-native StyleSheet node_modules/react-native/Libraries/StyleSheet/StyleSheet.js

Tệp tsconfig.json của tôi trông như sau:

{
  "compilerOptions": {
    "target": "es2016",
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react",
    "outDir": "artifacts",
    "rootDir": "src",
    "allowSyntheticDefaultImports": true,
    "noImplicitAny": false,
    "preserveConstEnums": true,
    "allowJs": true,
    "pretty": true,
    "sourceMap": true,
    "noImplicitReturns": true,
    "noUnusedParameters": true,
    "noUnusedLocals": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "importHelpers": true,
    "paths": {
      "*": ["src/*"]
    }
  },
  "include": ["./src/**/*"],
  "filesGlob": ["typings/index.d.ts", "src/**/*.ts", "src/**/*.tsx"],
  "types": ["react", "react-native", "jest"],
  "exclude": ["android", "ios", "build", "node_modules", "**/*.js"],
  "compileOnSave": false,
  "lib": ["dom", "es7"]
}

Tôi đã tìm kiếm trên web để tìm manh mối, thử thay đổi các giá trị của transformIgnorePatterns và tsconfig nhưng không thành công.

Khi tôi chạy dự án trên iOS/Android, nó biên dịch và hoạt động mà không gặp bất kỳ vấn đề nào.

Đây là kho lưu trữ:

https://github.com/ishabo/clate