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

Fails to compile typescript enums #761

Closed
dewey92 opened this issue May 27, 2021 · 12 comments
Closed

Fails to compile typescript enums #761

dewey92 opened this issue May 27, 2021 · 12 comments
Assignees
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler cat: typings 👮 Typescript types related issues needs: complete repro 🖥️ Issue need to have complete repro provided

Comments

@dewey92
Copy link

dewey92 commented May 27, 2021

Environment

  • Linaria version: ^2.1.0 (also tried with ^3.0.0-beta.4)
  • Bundler (+ version): Webpack ^4.44.2
  • Node.js version: 12.9.1
  • OS: Linux (Manjaro) and MacOS

Description

TS enums are always evaluated to undefined, producing this error:

ERROR in ./src/App.tsx
Module build failed (from ./node_modules/linaria/loader.js):
SyntaxError: /path/to/repo/src/App.tsx: An error occurred when evaluating the expression: 

  > Cannot read property 'black' of undefined. 

  Make sure you are not using a browser or Node specific API and all the variables are available in static context.
  Linaria have to extract pieces of your code to resolve the interpolated values.
  Defining styled component or class will not work inside:
    - function,
    - class,
    - method,
    - loop,
  because it cannot be statically determined in which context you use them.
  That's why some variables may be not defined during evaluation.
      
  10 |
  11 | const H1 = styled.h1`
> 12 | 	color: ${Color.black};
     |      	   ^^^^^^^^^^^
  13 | `

Reproducible Demo

enum Color {
  black = '#000'
}

const H1 = styled.H1`
  color: ${Color.black};
`

export default App() {
  return <H1>Error</H1>
}

You can also try replacing that enum with the transpiled code and it will still fail:

let Color;
(function (Color) {
    Color["black"] = "#000";
})(Color || (Color = {}));

const H1 = styled.H1`
  color: ${Color.black};
`

export default App() {
  return <H1>Error</H1>
}

So it seems like it doesn't run IIFEs

Other configs

webpack

module.exports = () => ({
  ...irrelevant,
  module: {
    rules: [
      {
        include: [resolve('src')],
        test: /\.(j|t)sx?$/,
        use: ['babel-loader', 'linaria/loader'],
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: resolve('./css-bundles/[name].css'),
    }),
  ],
})

.babelrc

{
  "presets": [
    "@babel/preset-typescript",
    "@babel/preset-react",
    "linaria/babel"
  ]
}
@dewey92 dewey92 added bug report 🦗 Issue is probably a bug, but it needs to be checked needs: complete repro 🖥️ Issue need to have complete repro provided needs: triage 🏷 Issue needs to be checked and prioritized labels May 27, 2021
@github-actions github-actions bot added bundler: webpack 📦 Issue is related to webpack bundler cat: typings 👮 Typescript types related issues and removed needs: triage 🏷 Issue needs to be checked and prioritized labels May 27, 2021
@PierreGUI
Copy link

PierreGUI commented May 27, 2021

More data

The code above does not build neither for Linaria versions 3-beta, 2, 1.4, 1.3 with both evaluators extractor and shaker.

Now, take the Color enum and move it to a separate file, like so:

import { Color } from './constants/style'

const H1 = styled.h1`
	color: ${Color.black};
`

And it builds for Linaria 1.4 and 2.1 as long as evaluator is set to extractor. It fails for shaker evaluator.

@Anber
Copy link
Collaborator

Anber commented May 30, 2021

Hi @dewey92 and @PierreGUI

I've fixed that issue, but I don't sure yet, that the fix doesn't break anything else. I need a couple of days for additional testing.

@dewey92
Copy link
Author

dewey92 commented May 31, 2021

@Anber Thanks for the fix! We can also help you test your fix 🙂 We'll let you know if we encounter problems, considering we use enums a lot in our linaria codebase

@Anber
Copy link
Collaborator

Anber commented May 31, 2021

Ok!
I'll publish it as a new beta later today.

@Anber
Copy link
Collaborator

Anber commented May 31, 2021

Published

@Anber Anber closed this as completed May 31, 2021
@dewey92
Copy link
Author

dewey92 commented Jun 1, 2021

Super thanks @Anber! I think it solves the enum problem, great job!

However, I found a new interesting bug in our codebase: It's when you import an enum:

/* constants/styles.ts */
export enum Size {
  xs = 'xs',
  ...
  xxl = 'xxl'
}

/* another_constants/avatar.ts */
import { Size } from 'constants/styles'

export const AvatarSize = {
  [Size.xs]: 20,
  ...
  [Size.xxl]: 50
}

/* Component.tsx  */
import { styled } from '@linaria/react'
import { AvatarSize } from 'nother_constants/avata'

const Avatar = styled.div`
  height: ${AvatarSize.xxl}px;
`

The error message:

Module build failed (from ./node_modules/@linaria/webpack-loader/lib/index.js):
SyntaxError: /path/to/project/Component.tsx: The expression evaluated to 'undefined',
which is probably a mistake. If you want it to be inserted into CSS,
explicitly cast or transform the value to a string, e.g. - 'String(AvatarSize.xxl)'.

  90 | const Avatar = styled.div`
> 91 | 	height: ${AvatarSize.xxl}px;
     |            ^^^^^^^^^^^^^^
  92| `

@Anber
Copy link
Collaborator

Anber commented Jun 1, 2021

Hmm… I couldn't reproduce it but I'll try again later today. Thank you for the report! :)

@Anber
Copy link
Collaborator

Anber commented Jun 24, 2021

Hi @dewey92!

Two days ago @M1r1k reproduced the issue with broken imports (#333) and I really hope that your issue has the same root. Could you please check 3.0.0-beta.7?

@dewey92
Copy link
Author

dewey92 commented Jun 26, 2021

@Anber will try next week! Thanks for letting me know 😉

@dewey92
Copy link
Author

dewey92 commented Jun 29, 2021

@Anber Thanks for creating a patch! After updating to 3.0.0-beta.7 unfortunately I still have the same issue 😕

I've prepared a minimal reproducable repo if you want to fiddle around https://github.com/dewey92/linaria-v3-iife-repro. Sorry if this is the least I could do to help you pinpoint the problem

@Anber
Copy link
Collaborator

Anber commented Jul 11, 2021

Hi @dewey92!
How did you get that code? If you try to evaluate it in a browser's console, you will get the same undefined.
The correct version of a transpilled enum should look like

var Color;
(function (Color) {
	Color = {}
	Color['black'] = '#000'
})(Color)

https://www.typescriptlang.org/play?#code/KYOwrgtgBAwg9gGzgJygbwFAEgBGCCGAxgNZQC8UA5AMQAM9lGAvhkA

@dewey92
Copy link
Author

dewey92 commented Jul 11, 2021

@Anber My bad! With the latest patch my issue-reproduction repo does indeed work. But in our project it's still not compiling, complaining it's undefined.

Let me close the issue until I figure out the exact problem. Thanks once again 🙂

@dewey92 dewey92 closed this as completed Jul 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler cat: typings 👮 Typescript types related issues needs: complete repro 🖥️ Issue need to have complete repro provided
Projects
None yet
Development

No branches or pull requests

3 participants