通过打字稿中的动态键获取对象值

时间:2020-07-01 20:56:07

标签: javascript reactjs typescript

我试图仅根据process.env.NODE_ENV的值导出配置对象的1个值,所以我试图获取configEnvs之类的configEnvs['local']变量的值,但是尝试访问该对象的一个​​键时出现错误。我尝试使用enum作为键来设置可能的值,但是没有用。

我目前正在尝试使用getKeyValue来获取键值,该键获取对象并将键值限制为仅对象的键,但是它表示我正在尝试的string通过密钥不能分配给可能的选项。

const getKeyValue = <T, K extends keyof T>(obj: T, key: K) => obj[key];

const { NODE_ENV, REACT_APP_ENV } = process.env;

interface IConfigEnv {
  DB_DNS: string;
}
interface IConfig {
  local: IConfigEnv;
  development: IConfigEnv;
  production: IConfigEnv;
}

let configEnvs: IConfig = {
  local: {
    DB_DNS: "https://localhost:4000",
  },

  development: {
    DB_DNS: "https://my-dev.web.com",
  },

  production: {
    DB_DNS: "https://api.web.com",
  },
};

const nodeEnv = REACT_APP_ENV || NODE_ENV || "development";
const config: IConfigEnv = getKeyValue(configEnvs, nodeEnv);

export default config; 

我在声明config时遇到此错误:

Argument of type 'string' is not assignable to parameter of type '"development" | "production" | "local"'.

2 个答案:

答案 0 :(得分:0)

我像这样使用Type Assertion解决了这个问题:

export type NODE_ENVIRONMENTS = "local" | "development" | "production";

// Here using 'as' keyword
const NODE_ENV: NODE_ENVIRONMENTS = process.env.NODE_ENV as NODE_ENVIRONMENTS;
const REACT_APP_ENV: NODE_ENVIRONMENTS = process.env
  .REACT_APP_ENV as NODE_ENVIRONMENTS;

interface IConfigEnv {
  DB_DNS: string;
}

interface IConfigEnv {
  DB_DNS: string;
}
interface IConfig {
  local: IConfigEnv;
  development: IConfigEnv;
  production: IConfigEnv;
}

const config: IConfig = {
  local: {
    DB_DNS: "https://localhost:4000",
  },

  development: {
    DB_DNS: "https://api-dev.web.com",
  },

  production: {
    DB_DNS: "https://api.web.com",
  },
};

const nodeEnv: NODE_ENVIRONMENTS = REACT_APP_ENV || NODE_ENV || "development";

export default config[nodeEnv];

答案 1 :(得分:0)

更安全的方法是使用类似 typeguard or type assertion function 之类的东西:

interface IConfigEnv {
  DB_DNS: string;
}
interface IConfig {
  local: IConfigEnv;
  development: IConfigEnv;
  production: IConfigEnv;
}

const acceptableEnvs = [ "local", "development", "production" ];
function assertEnv(k: any): asserts k is keyof IConfig {
  if (typeof k !== "string" || !acceptableEnvs.includes(k)) {
    throw new Error(
      `Environment must be one of '${acceptableEnvs.join("', '")}'. You passed '${k}'.`
    );
  }
}

const config: IConfig = {
  local: {
    DB_DNS: "https://localhost:4000",
  },

  development: {
    DB_DNS: "https://api-dev.web.com",
  },

  production: {
    DB_DNS: "https://api.web.com",
  },
};

const nodeEnv = process.env.REACT_APP_ENV || process.env.NODE_ENV || "development";

assertEnv(nodeEnv);

export default config[nodeEnv];

请注意,此解决方案明确了应用程序可能会抛出的错误,如果您只是简单地将错误的运行时值进行类型转换,则为您提供了对流程的更多控制和确定性。也就是说,如果/当它被抛出时,你仍然必须确保处理该错误。