Search code examples
typescripttsconfig

How to get tsconfig to recognize ".graphql" files, aliases, when importing them into components?


So, I am including some "graphql" files into my components and they are giving me TS errors because the import pathing isn't recognized. It all works, just gives the TS error.

import QUERY_GET_CATS from "@gql/GetCats.graphql";

error that I am getting: TS2307: Cannot find module '@gql/GetCat.graphql' or its corresponding type declarations

Here is my tsconfig:

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "*": [
        "./*"
      ],
      "@gql/*": [
        "./api/gql/*"
      ]
    },
    "lib": ["dom", "dom.iterable", "esnext"],
    "strict": true,
    "noUnusedLocals": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "isolatedModules": true,
    "jsx": "preserve",
    "downlevelIteration": true,
    "allowJs": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  },
  "exclude": [
    "cypress",
    "coverage",
    "node_modules",
    "build",
    "dist",
    "out",
    ".next",
    "next.config.js",
    "./**/*.js",
    "./**/*.jsx",
    "./**/*.scss"
  ],
  "include": [
    "next-env.d.ts",
    "./**/*.ts",
    "./**/*.tsx"
  ]
}

my eslintrc

const path = require('path');

module.exports = {
  parserOptions: {
    ecmaVersion: 2019,
    sourceType: 'module',
    project: './tsconfig.json',
    ecmaFeatures: {
      jsx: true,
    },
  },
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:react-hooks/recommended',
    'plugin:react/recommended',
    'airbnb-typescript',
    'prettier',
    'prettier/react',
    'eslint-config-prettier',
    'eslint-config-prettier/@typescript-eslint',
    'plugin:cypress/recommended'
  ],
  globals: {
    cy: true
  },
  rules: {
    strict: ['error', 'never'],
    'import/no-cycle': 0,
    'import/prefer-default-export': 0,
    'global-require': 0,
    'react/jsx-key': 1,
    'prefer-destructuring': 1,
    "import/no-extraneous-dependencies": 1,
    'no-console': 'warn',
    'no-param-reassign': [
      2,
      {
        props: false,
      },
    ],
    'react/prop-types': 0,
    'camelcase': ['warn', {ignoreDestructuring: true, properties: 'never'}],
    'react/no-unescaped-entities': 0,
    'import/extensions': 'off',
    'react/jsx-props-no-spreading': ['warn', {custom: 'ignore'}],
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/no-static-element-interactions': 0,
  },
  env: {
    browser: true,
    jest: true,
    es2020: true,
    'cypress/globals': true,
  },
  plugins: ['eslint-plugin-cypress'],
  overrides: [
    {
      settings: {
        'import/resolver': {
          jest: {
            jestConfigFile: path.join(__dirname, '/jest.config.js'),
          },
        },
      },
    },
  ],
};

Note: when I added "./**/*.graphql" to the "include" array, didn't help. Note: my other aliases work. Just not the "graphql" ones.


Solution

  • Because these files are gql syntax, and not part of the Typescript lexicon, you need to define them as an ambient module in a type definitions file as described in the typescript docs.

    documentNode.d.ts

    declare module '*.graphql' {
      import {DocumentNode} from 'graphql';
    
      const value: DocumentNode;
      export = value;
    }
    

    You'll need to add "./**/*.graphql" to the include section of your tsconfig as well.

    It should be noted, that this is basically a dummy/placeholder that lets you import the files in your codebase, but won't derive any type information from the contents. There's a package from the folks at graphql code generator called TypedDocumentNode that lets you pull fully typed DocumentNodes into your project, but I have not tried it so YMMV.