Search code examples
reactjstypescripteslintstyled-components

"Missing return type on function" error in styled component interpolation function


The interpolation function used for extracting theme data from props yields a "Missing return type on function." eslint error. I have used declaration merging to type my theme data as explained in typescript documentation. The merging seems to work correctly because props.theme is typed according to my declarations.

The problem can be fixed by specifying a return type for the interpolation function

${(props): string => props.theme.colors.secondary}

but I don't think that should be necessary because I have already specified the type of props.theme.colors.secondary in the type declarations file. Furthermore, in the vs code error popup it seems that the return type is known (function(...): string), but the error is still given.

Code in GitHub.

// App.tsx
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import theme from 'theme/default';

const StyledApp = styled.div`
  // The error is caused by this interpolator function     
  background-color: ${(props) => props.theme.colors.secondary};
`;
// styled.d.ts
import 'styled-components';

// Extend the default theme type
declare module 'styled-components' {
  export interface DefaultTheme {
    colors: {
      primary: string;
      primaryLight: string;
      primaryLighter: string;
      primaryDark: string;
      secondary: string;
      secondaryLight: string;
      secondaryDark: string;
      font: string;
    };
  }
}
// theme/default.tsx
import { DefaultTheme } from 'styled-components';

const theme: DefaultTheme = {
  colors: {
    primary: 'hsl(0, 98%, 33%)',
    primaryLight: 'hsl(359, 98%, 41%)',
    primaryLighter: 'hsl(14, 54%, 52%)',
    primaryDark: 'hsl(2, 90%, 20%)',
    secondary: 'hsl(260, 4%, 31%)',
    secondaryLight: 'hsl(35, 13%, 45%)',
    secondaryDark: 'hsl(0, 14%, 1%)',
    font: 'hsl(317, 7%, 79%)'
  }
};

export default theme;
// .eslintrc.js
module.exports = {
  env: {
    browser: true
  },
  parser: '@typescript-eslint/parser',
  extends: [
    'airbnb',
    'airbnb/hooks',
    'plugin:@typescript-eslint/recommended',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended'
  ],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module'
  },
  rules: {
    'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
    'react/prop-types': 'off'
  },
  settings: {
    'import/extensions': ['.js', '.jsx', '.ts', '.tsx'],
    'import/parsers': {
      '@typescript-eslint/parser': ['.ts', '.tsx']
    },
    'import/resolver': {
      node: {
        paths: 'src',
        extensions: ['.js', '.jsx', '.ts', '.tsx']
      }
    }
  }
};
// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "baseUrl": "src"
  },
  "include": ["src"]
}
    // deps
    "@types/react": "16.9.2",
    "@types/react-dom": "16.9.0",
    "@types/styled-components": "^4.1.18",
    "overmind": "^19.1.1",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-scripts": "3.1.1",
    "styled-components": "^4.3.2",
    "typescript": "3.6.2"
    "@typescript-eslint/eslint-plugin": "^2.1.0",
    "@typescript-eslint/parser": "^2.1.0",
    "babel-core": "^7.0.0-bridge.0",
    "eslint": "^6.1.0",
    "eslint-config-airbnb": "^18.0.1",
    "eslint-config-prettier": "^6.2.0",
    "eslint-plugin-import": "^2.18.2",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-prettier": "^3.1.0",
    "eslint-plugin-react": "^7.14.3",
    "eslint-plugin-react-hooks": "^1.7.0",
    "prettier": "^1.18.2"

The error popup in vs code The error popup in vs code


Solution

  • I was able to fix the problem by adding the following rule to my .eslintrc.js

    '@typescript-eslint/explicit-function-return-type': [
          'error',
          {
            allowExpressions: true
          }
    ]
    

    It allows function expressions to not have an explicitely defined return type, which removes the missing return type error from styled components' interpolator functions as they are funcion expressions.

    This solution simply turns the error off instead of fixing it directly.