在分配变量之前使用变量的常见模式

Vad*_*dim 3 typescript

我有一个模块

import pino, { Logger } from 'pino';

let logger: Logger;

if (process.env.NODE_ENV === 'production') {
    const dest = pino.extreme();
    logger = pino(dest);
}

if (process.env.NODE_ENV === 'development') {
    // @ts-ignore
    logger = pino({ prettyPrint: { colorize: true } });
}

...

export default logger;
// ^^^ [ts] Variable 'logger' is used before being assigned. [2454]
Run Code Online (Sandbox Code Playgroud)

在未定义logger的情况下,没有任何情况,但即使它是未定义的,它也会替我

最后如何解决TypeScript错误:

变量“ logger”在分配前已使用。[2454]

我已经重写了代码,但错误仍然存​​在

import pino, { Logger } from 'pino';

let logger: Logger;

if (process.env.NODE_ENV === 'production') {
    const dest = pino.extreme();
    logger = pino(dest);
} else 

if (process.env.NODE_ENV === 'development') {
    // @ts-ignore
    logger = pino({ prettyPrint: { colorize: true } });
} else

if (process.env.NODE_ENV === undefined) {
    throw new Error('Logger must be initialized! Set up process.env.NODE_ENV');
}

if (logger) { // <-- Variable 'logger' is used before being assigned. [2454]
   // configuring process
}

export default logger;
Run Code Online (Sandbox Code Playgroud)

即使以另一种方式

import pino, { Logger } from 'pino';

let logger: Logger;

function configureProcess(theLogger: Logger) {
  // setup process with theLogger
}

if (process.env.NODE_ENV === 'production') {
    const dest = pino.extreme();
    logger = pino(dest);
    configureProcess(logger); // <-- code duplication
} else if (process.env.NODE_ENV === 'development') {
    // @ts-ignore
    logger = pino({ prettyPrint: { colorize: true } });
    configureProcess(logger); // <-- code duplication
}

if (process.env.NODE_ENV === undefined) {
    throw new Error('Logger must be initialized! Set up process.env.NODE_ENV');
}

export default logger;
// ^^^ [ts] Variable 'logger' is used before being assigned. [2454]
Run Code Online (Sandbox Code Playgroud)

我感觉自己像是反对TypeScrit的斗士,而不是开发者-如此众多的舞蹈解决了一个实际上不是问题的问题(

T.J*_*der 6

但即使它不确定,也对我而言

我建议有loggerBE undefined是不是一个好主意(详见下文),但基于您的上述声明:

向编译器和代码维护者明确说明:

switch (process.env.NODE_ENV) {
    case 'production':
        const dest = pino.extreme(); // logs to stdout with no args
        logger = pino(dest);
        break;
    case 'development':
        // @ts-ignore
        logger = pino({ prettyPrint: { colorize: true } });
        break;
    default:
        logger = undefined; // That's fine
        break;
}
Run Code Online (Sandbox Code Playgroud)

(不必是switchif/ else if/ else也可以。)

还要注意,正如VinceOPS指出的那样,您需要允许logger具有该值:undefined

let logger: Logger | undefined;
Run Code Online (Sandbox Code Playgroud)

注意:这意味着任何使用 logger都必须允许其具有值undefined。如果我是你,我不会那样做。代替:

  1. 如果您只需要支持两种配置,请列出:

    1. 仅检查其中一个,然后假设另一个:

      if (process.env.NODE_ENV === 'development') {
          case 'development':
              // @ts-ignore
              logger = pino({ prettyPrint: { colorize: true } });
      } else { // production
              const dest = pino.extreme(); // logs to stdout with no args
              logger = pino(dest);
      }
      
      Run Code Online (Sandbox Code Playgroud)

      要么

    2. 在第三个分支中引发错误:

      switch (process.env.NODE_ENV) {
          case 'production':
              const dest = pino.extreme(); // logs to stdout with no args
              logger = pino(dest);
              break;
          case 'development':
              // @ts-ignore
              logger = pino({ prettyPrint: { colorize: true } });
              break;
          default:
              throw new Error("process.env.NODE_ENV must be either 'production' or 'development' to use this module");
      }
      
      Run Code Online (Sandbox Code Playgroud)
  2. 如果要支持所有三种可能性(productiondevelopment或都不支持),请在第三个分支中也初始化logger为有效值Logger,也许是“不执行任何操作”记录器。

这比让好多loggerundefined

  • 同样,这似乎是一个不好的让步,每个导入记录器的模块现在都必须在使用前进行“未定义”检查。无需使其变得不确定,请参见我的答案以获取没有`undefined`警告的更简单的解决方案 (2认同)

Vin*_*OPS 6

或者更简单,假设:

但即使它是未定义的,它也适合我

代替

let logger: Logger;  
Run Code Online (Sandbox Code Playgroud)

let logger: Logger | undefined;
Run Code Online (Sandbox Code Playgroud)

如果logger 可以未定义,则将其注释为可能未定义。以后tsc不会再抱怨了。

  • 这解决了一个与 OP 询问的问题不同的问题(但这是他们的**下一个**问题:-))。 (2认同)
  • 您在这里对 OP 的代码库/业务逻辑做出假设;我的答案仅涉及“tsc”和类型推断,即使“logger”被称为“foo”且类型为“Bar”,也不会改变。导入它的“其他模块”将被告知其可能的_未定义_,这就是 TypeScript 真正强大的地方。我在这里没有看到链接/问题。无论如何,我希望所提出的解决方案之一适合OP!祝你今天过得愉快。 (2认同)