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

importMetaEnv doesn't work. #3524

Closed
socketbear opened this issue May 24, 2021 · 23 comments
Closed

importMetaEnv doesn't work. #3524

socketbear opened this issue May 24, 2021 · 23 comments
Labels
cannot reproduce The bug cannot be reproduced

Comments

@socketbear
Copy link

Describe the bug

I used the intellisense function as per the guide, but it doesn't work.

/src/env.d.ts

interface ImportMetaEnv {
  VITE_API_TIMEOUT: number,
  VITE_MOCKUP: boolean
}

.env

VITE_API_TIMEOUT=3000
VITE_MOCKUP=true

And, when import.meta.env is printed from main.ts to the console...

BASE_URL: "/"
DEV: true
MODE: "development"
PROD: false
SSR: false
VITE_API_TIMEOUT: "3000"
VITE_MOCKUP: "true"
VITE_SET: "900"

Intellisense does not work for .env settings. It only comes in string type.

Reproduction

I want it to be converted to the type applied in intellisense (env.d.ts).

System Info

package.json

  "devDependencies": {
    "@antfu/eslint-config": "^0.6.5",
    "@iconify/json": "^1.1.347",
    "@intlify/vite-plugin-vue-i18n": "^2.1.2",
    "@types/nprogress": "^0.2.0",
    "@typescript-eslint/eslint-plugin": "^4.24.0",
    "@vitejs/plugin-vue": "^1.2.2",
    "@vue/compiler-sfc": "^3.0.11",
    "@vue/server-renderer": "^3.0.11",
    "cross-env": "^7.0.3",
    "eslint": "^7.27.0",
    "https-localhost": "^4.6.5",
    "markdown-it-prism": "^2.1.6",
    "npm-run-all": "^4.1.5",
    "pnpm": "^6.4.0",
    "sass": "^1.34.0",
    "typescript": "^4.2.4",
    "vite": "^2.3.3",
    "vite-plugin-components": "^0.9.1",
    "vite-plugin-icons": "^0.5.1",
    "vite-plugin-md": "^0.6.7",
    "vite-plugin-pages": "^0.12.1",
    "vite-plugin-pwa": "^0.7.3",
    "vite-plugin-vue-layouts": "^0.3.1",
    "vite-plugin-windicss": "^0.15.10",
    "vite-ssg": "^0.11.1",
    "vue-tsc": "^0.1.4"
  }

Used package manager: pnpm

@Shinigami92
Copy link
Member

Could you try

interface ImportMetaEnv {
  readonly VITE_API_TIMEOUT: number;
  readonly VITE_MOCKUP: boolean;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

@socketbear
Copy link
Author

@Shinigami92 Tried the way you gave.
But it's the same problem...
It doesn't seem to be reading the env.d.ts file.
For reference, the env.d.ts file is under src.
(same location as main.ts)

@haoqunjiang
Copy link
Member

Can't reproduce. It works on my machine.

@haoqunjiang haoqunjiang added cannot reproduce The bug cannot be reproduced and removed pending triage labels May 25, 2021
@znerol
Copy link

znerol commented May 26, 2021

Related to #3214 and docs on client-types. You have two options:

  1. Reference the vite/client types env.d.ts file:
    /// <reference types="vite/client" />
    
    interface ImportMetaEnv {
      VITE_API_TIMEOUT: number,
      VITE_MOCKUP: boolean
    }
  2. Add the "types": ["vite/client"] into the compilerOpions of your tsconfig.json file.

PR #3214 just migrated the create-app command from option 2 to option 1.

@mrerhuo
Copy link

mrerhuo commented Jun 9, 2021

I don't understand, how to solve it?

@Zenthae
Copy link

Zenthae commented Jul 25, 2021

@mrerhuo
when you start a new project a vite-end.d.ts is created, You just need to update it like this

vite-env.d.ts

/// <reference types="vite/client" />

interface ImportMetaEnv {
  YOUR_PROP: string;
}

then you can use it like this import.meta.env.YOUR_PROP.

@AgainPsychoX
Copy link

AgainPsychoX commented Sep 3, 2021

I don't think the types are converted by default. You have to do it yourself.

I think the env.d.ts is just a way to fight annoyance of import.meta.env values being typed as string | boolean | undefined, when it mostly should be string | undefined. Sadly, it's because there are DEV and PROD keys in import.meta.env that are booleans. I think there could be fix introduced, but it's not yet done - anyway, it would just make the defining own ImportMetaEnv unnecessary, the values still would be string | undefined.

Anyway, the solution is to convert the types by yourself.

If you want some inspiration for now, I use it like this in my project:
config.ts, website sources:

const parseBoolean = (value: string | boolean | undefined, defaultValue: boolean) => {
	if (typeof value === 'undefined') {
		return defaultValue;
	}
	if (typeof value === 'boolean') {
		return value;
	}
	switch (value.toLowerCase().trim()) {
		case "true": case "yes": case "1": return true;
		case "false": case "no": case "0": return false;
		default: return defaultValue;
	}
}

const Config = {
	isDev: import.meta.env.DEV,
	firebaseConfig: {
		apiKey:                 import.meta.env.VITE_FIREBASE_API_KEY,
		authDomain:             import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
		databaseURL:            import.meta.env.VITE_FIREBASE_DATABASE_URL,
		projectId:              import.meta.env.VITE_FIREBASE_PROJECT_ID,
		storageBucket:          import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
		messagingSenderId:      import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
		appId:                  import.meta.env.VITE_FIREBASE_APP_ID,
		measurementId:          import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
	},
	useEmulators: parseBoolean(import.meta.env.VITE_USE_EMULATORS, import.meta.env.DEV),
};

export default Config;

env.d.ts:

interface ImportMetaEnv {
	VITE_FIREBASE_API_KEY:              string | undefined;
	VITE_FIREBASE_AUTH_DOMAIN:          string | undefined;
	VITE_FIREBASE_DATABASE_URL:         string | undefined;
	VITE_FIREBASE_PROJECT_ID:           string | undefined;
	VITE_FIREBASE_STORAGE_BUCKET:       string | undefined;
	VITE_FIREBASE_MESSAGING_SENDER_ID:  string | undefined;
	VITE_FIREBASE_APP_ID:               string | undefined;
	VITE_FIREBASE_MEASUREMENT_ID:       string | undefined;

	VITE_USE_EMULATORS:                 string | undefined;

	VITE_WEBSITE_URL:                   string | undefined;

	VITE_APP_LOCALHOST_PORT:            string | undefined;
	VITE_WEBSITE_LOCALHOST_PORT:        string | undefined;
}

My code base imports Config where necessary, it have types nicely converted.

@imShara
Copy link
Contributor

imShara commented Nov 4, 2021

Recommended in docs way to add types causes build problem:

interface ImportMetaEnv extends Readonly<Record<string, string>> {
  readonly VITE_VAR: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}
▶ pnpm build

> [email protected] build /test
> vue-tsc --noEmit && vite build

node_modules/.pnpm/[email protected]/node_modules/vite/types/importMeta.d.ts:62:11 - error TS2430: Interface 'ImportMetaEnv' incorrectly extends interface 'Readonly<Record<string, string>>'.
  'string' index signatures are incompatible.
    Type 'string | boolean | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.

62 interface ImportMetaEnv {
             ~~~~~~~~~~~~~


Found 1 error.

 ELIFECYCLE  Command failed with exit code 2.

This works

interface ImportMetaEnv extends Readonly<Record<string, string | boolean | undefined>> {
  readonly VITE_VAR: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

@Shinigami92
Copy link
Member

@imShara I can confirm this 👍

Correct would be without extends Readonly<Record ... and maybe I think with the ///ref

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_VAR: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

@imShara
Copy link
Contributor

imShara commented Nov 5, 2021

@Shinigami92, I'm newbie in typescrypted vue, can you explain your suggestion?

@Shinigami92
Copy link
Member

My suggestion would be to open a new PR and update the documentation with exactly my example above 🙂

@imShara
Copy link
Contributor

imShara commented Nov 6, 2021

@Shinigami92, I mean why your version correct, not mine? Why you drop extends Readonly reference?

@Shinigami92
Copy link
Member

Maybe Readonly<Record<string, string>> could work, feel free to try it out

@imShara
Copy link
Contributor

imShara commented Nov 6, 2021

Maybe Readonly<Record<string, string>> could work, feel free to try it out

No, it not works, because record's value type can be string | boolean | undefined as linter suggested.

@Shinigami92
Copy link
Member

Shinigami92 commented Nov 6, 2021

As far as I know, only the non VITE_ (DEV, PROD and SSR) can be of type boolean. All others are only string or undefined.

@imShara
Copy link
Contributor

imShara commented Nov 6, 2021

But .env file could store non VITE_ variables too

@Shinigami92
Copy link
Member

You referring to this? #4194
Yeah, okay but these can still be only strings. All variables defined in .env can only be string.

imShara added a commit to imShara/vite that referenced this issue Nov 7, 2021
```
node_modules/.pnpm/[email protected]/node_modules/vite/types/importMeta.d.ts:62:11 - error TS2430: Interface 'ImportMetaEnv' incorrectly extends interface 'Readonly<Record<string, string>>'.
  'string' index signatures are incompatible.
    Type 'string | boolean | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.

62 interface ImportMetaEnv {
             ~~~~~~~~~~~~~
```

More info in this thread vitejs#3524 (comment)
@erdemtuna
Copy link

Hi, I cannot access my environment variable prefixed properly "VITE_APP_TITLE" inside my code. I try to access it with "import.meta.env.VITE_APP_TITLE" in typescript. Do you have any idea about it? .env file is in root folder. I have put the code below in env.d.ts file

interface ImportMetaEnv {
    readonly VITE_APP_TITLE: string
    // more env variables...
}

interface ImportMeta {
    readonly env: ImportMetaEnv
}

@jromerooo2
Copy link

Hey, I faced the same issue, what I did is in my vite.config.js I used it like this:

code

@erdemtuna
Copy link

@jromerooo2 thank you for the resolution. The vitejs guide tells that env[key] style will fail in production mode as in https://vitejs.dev/guide/env-and-mode.html#production-replacement. How did you resolve the mentioned potential problem in the guide?

@jromerooo2
Copy link

@erdemtuna I used "?" on the env variable name. As mentioned here:

https://stackoverflow.com/questions/66039933/typescript-types-for-import-meta-env

@bluwy
Copy link
Member

bluwy commented Feb 26, 2022

Is this still an issue? It works for me following https://vitejs.dev/guide/env-and-mode.html#intellisense-for-typescript

@bluwy
Copy link
Member

bluwy commented Mar 9, 2022

Closing as the documentation has been updated with the correct way of typing ImportMetaEnv. Please open a discussion if there's still issues with it. It would likely be an issue with configuring tsconfig.

@bluwy bluwy closed this as completed Mar 9, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Mar 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cannot reproduce The bug cannot be reproduced
Projects
None yet
Development

No branches or pull requests