pizzajuice
pizzajuice

Reputation: 176

Typescript says NextJS environment variables are undefined

I'm trying to make social login using 'react-google-login'.

.env in root

NEXT_PUBLIC_GOOGLE_CLIENT_ID=askfjaskf

Ready.tsx

import { GoogleLogin } from "react-google-login";
<GoogleLogin
    clientId={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID}
    render={(props) => (
      <div onClick={props.onClick}>
        <div>구글 로그인</div>
      </div>
    )}
    onSuccess={(res) => {
      const { profileObj } = res as any;
      setStep(AuthStep.AGREE);
    }}
    onFailure={(res) => {
      console.log("Google Error", res);
    }}
  />

And in clientId, it says

No overload matches this call. Overload 1 of 2, '(props: GoogleLoginProps | Readonly): GoogleLogin', gave the following error. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'. Overload 2 of 2, '(props: GoogleLoginProps, context: any): GoogleLogin', gave the following error. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2769) index.d.ts(80, 12): The expected type comes from property 'clientId' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes & Readonly & Readonly<...>'

I don't know why it says it can be undefined. And it works on local but it doesn't work in production deployment. Anyone can help?

Upvotes: 11

Views: 15290

Answers (4)

Ndeto
Ndeto

Reputation: 315

This is old but it might help. The reason why the normal .env.local variables might not be working in some places, is because NextJS avails them in API Routes and Data Fetching helpers but not elsewhere. For typescript we need to load them into the project. So this worked for me in my NextJS project. I put this inside next.config.mjs

import path from 'path';
import { config } from 'dotenv';

// Load environment variables from `.env.local` file
const { parsed: localEnv } = config({
  allowEmptyValues: false,
  path: path.resolve(process.cwd(), '.env.local'),
});

const nextConfig = {
  env: localEnv,
};

export default nextConfig;

Upvotes: 0

mrkosima
mrkosima

Reputation: 506

The answer with declare global { ... didn't work out for me.

The recommanded approach is to create a type declaration file, for example env.d.ts with the following declaration:

declare namespace NodeJS {
  interface ProcessEnv {
    JWT_TOKEN: string;
  }
}

And then add this reference in your tsconfig.json file's include:

{
    "include": [
        "next-env.d.ts",
        "env.d.ts",
    ]
}

Discouraged approach

Do not add a reference in next-end.d.ts, Next.js docs mention that:

A file named next-env.d.ts will be created at the root of your project [...] You should not remove it or edit it as it can change at any time.

Instead, please use a recommended approach:

Instead of editing next-env.d.ts, you can include additional types by adding a new file e.g. additional.d.ts and then referencing it in the include array in your tsconfig.json.

Upvotes: 21

ilyasDev
ilyasDev

Reputation: 73

you need to cast it to a string

export default NextAuth({
providers: [
    GoogleProvider({
        clientId: process.env.GOOGLE_ID as string,
        clientSecret: process.env.GOOGLE_SECRET as string,
    }),
]})

Upvotes: 6

Jonni Trev
Jonni Trev

Reputation: 114

I had the same issue but with different ENV variable, the issue is typescript doesn't know if an ENV variable exists or not.

Check this other question: using process.env in TypeScript

It helped me fixing this problem. Just need to create the environment.d.ts and declare the global ENV variables as the type you want them to be

declare global {
  namespace NodeJS {
    interface ProcessEnv {
      NEXT_PUBLIC_GOOGLE_CLIENT_ID: string; // this is the line you want
      NODE_ENV: 'development' | 'production';
      PORT?: string;
      PWD: string;
    }
  }
}

Upvotes: 9

Related Questions