typewriter icon indicating copy to clipboard operation
typewriter copied to clipboard

Attempted import error: <enum> is not exported

Open pruett opened this issue 5 years ago • 10 comments

Really enjoying Typewriter. Thanks!

I ran in the following error when attempting to import types from analytics/generated/index.d.ts:

Attempted import error: 'SignupType' is not exported from '../../analytics/generated'.

This isn't likely a bug on Typewriter's part, but I'm struggling to proceed at this point.

Reproduction

Generated .d.ts file: (analytics/generated/index.d.ts)

export interface NewsletterSignup {
  /**
   * The type of form that was used to sign up for email
   */
  signup_type: SignupType
}

/**
 * The type of form that was used to sign up for email
 */
export enum SignupType {
  Callout = 'callout',
  Footer = 'footer'
}

analytics/index.ts

import Analytics from './generated'

declare global {
  interface Window {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    analytics: any
  }
}

export default Analytics

Usage:

import Analytics from '../../analytics'
import { SignupType } from '../../analytics/generated'

fn({ signup_type: SignupType.Footer }) // Attempted import error: 'SignupType' is not exported from '../../analytics/generated'

Any noticeable missteps on my part? Thanks.

pruett avatar Aug 02 '19 03:08 pruett

Curious if this reveals anything...

I changed the enum to a string literal type and it works as expected.

- export enum SignupType {
-   Callout = 'callout',
-   Footer = 'footer'
- }
+ export type SignupType = 'callout' | 'footer'

I'm new to TypeScript but curious if this makes sense. I'm assuming I'm using enums in an unintended way?

pruett avatar Aug 02 '19 14:08 pruett

The more I read about enums, the more I see that they are discouraged. Maybe this thread is really a question of "How to best use exported enums from the Typewriter-generated d.ts file?"

pruett avatar Aug 02 '19 15:08 pruett

Hey @pruett! Apologize for the delay here, thanks for digging in on it!

Which version of Typewriter are you using here? Are you able to see if you're still hitting this issue with the latest pre-release (typewriter@next)?

colinking avatar Oct 20 '19 20:10 colinking

~Heads up, we actually inline enums in the new pre-release of Typewriter, f.e.:~ Update -- see below.

export interface NewsletterSignup {
  /**
   * The type of form that was used to sign up for email
   */
  signup_type: 'callout' | 'footer'
}

Though I'd like to move to exported enums for the same use-case you brought up. Will leave this issue up until we've shipped enums to the new TS clients.

colinking avatar Oct 20 '19 20:10 colinking

Great, thanks for the update @colinking ! I will go ahead and update the library version and report back. Thanks!

pruett avatar Nov 06 '19 16:11 pruett

Hm. I'm actually not seeing this. I'm seeing

export interface NewsletterSignup {
  /**
   * The type of form that was used to sign up for email
   */
  signup_type: string
}

Despite the Protocols UI indicating the Data Type is an Enum

Edit:

$ ./node_modules/.bin/typewriter --version
Version: 7.0.0 (new! 7.0.0-48)

pruett avatar Nov 18 '19 15:11 pruett

Additionally, I'll include the JSON Schema below:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "description": "The user has signed up for our Newsletter",
  "properties": {
    "context": {
      "id": "/properties/context"
    },
    "traits": {
      "id": "/properties/traits"
    },
    "properties": {
      "type": "object",
      "properties": {
        "placement": {
          "description": "The placement of the newsletter signup form on the website",
          "enum": [
            "footer",
            "subscribe-module",
            "mega-nav"
          ],
          "type": "string",
          "id": "/properties/properties/properties/placement"
        }
      },
      "required": [
        "placement"
      ],
      "id": "/properties/properties"
    }
  }
}


It's possible we are generating our schemas incorrectly as we are maintaining a separate repository of .yaml files and constructing them before pushing them up to Segment via an API call. Let me know if anything stands out that looks incorrect. I will point out that removing "type": "string" does not appear to fix the generated client.

pruett avatar Nov 19 '19 22:11 pruett

Ah, I see what's going on. We're parsing enums from JSON Schemas into our AST: https://github.com/segmentio/typewriter/blob/b3c2c327b15ba08b4d5321345b4212d2ecdb3d3b/src/generators/ast.ts#L267-L277

But we're not overriding the outputted type (string etc.) with the set of enum values: https://github.com/segmentio/typewriter/blob/b3c2c327b15ba08b4d5321345b4212d2ecdb3d3b/src/generators/javascript/javascript.ts#L82-L84

Sounds like I 🤦‍♂ -ed and was thinking of how we support union types: https://github.com/segmentio/typewriter/blob/b3c2c327b15ba08b4d5321345b4212d2ecdb3d3b/src/generators/javascript/javascript.ts#L125-L129

This isn't a huge lift to add literal enums, but I'd like to move towards explicit enums, as you mentioned in the issue above. Will leave open until enums are shipped.

colinking avatar Nov 20 '19 20:11 colinking

Awesome! Thanks for looking into this and confirming the output! Also thanks for providing links to the pertinent code snippets!!

pruett avatar Nov 20 '19 21:11 pruett

Hey @pruett! We've got a pre-release out that includes enum support for the JS clients, if you want to give it a try (v7.0.2-0): https://github.com/segmentio/typewriter/pull/113

colinking avatar Dec 09 '19 19:12 colinking