TypeScript 中 Function lacks ending return statement 错误

当并非具有显式返回类型的函数的所有代码路径都返回值时,会出现“Function lacks ending return statement”错误。 要解决该错误,请从所有代码路径返回一个值或在函数的返回类型中包含 undefined。

以下是错误发生方式的 3 个常见示例。

// ⛔  Error:️ Function lacks ending return statement
// and return type does not include 'undefined'.ts(2366)
const getNumber = (): number => {
  if (Math.random() > 0.5) {
    return 100;
  }
  // ?️ No return value here ?️
};

const getPromise = async (): Promise<number> => {
  try {
    const result = await Promise.resolve(42);
    return result;
  } catch (err) {
    console.log(err);
    // ?️ No return value here ?️
    // TypeScript expects that all calls to function
    // return number (even erroneous ones)
  }
};

const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  } else if ('hello'.length === 6) {
    return 'hello';
  }
  // ?️ TypeScript doesn't know that ?️
  // getting here is impossible
};

让我们看看 3 个错误原因的解决方案。

在第一个示例中,我们明确地将函数的返回类型设置为数字,但并非所有代码路径都返回一个值。

要解决此错误,请确保从函数的所有代码路径返回一个值。

// ✅ Works now
const getNumber = (): number => {
  if (Math.random() > 0.5) {
    return 100;
  }

  return 50; // ?️ all code paths return a value
};

第二个示例显示了在函数中使用 try/catch 语句时错误是如何发生的,我们为此设置了 Promise<number> 的返回类型。

// ⛔  Error:️ Function lacks ending return statement
// and return type does not include 'undefined'.ts(2366)
const getPromise = async (): Promise<number> => {
  try {
    const result = await Promise.resolve(42);
    return result;
  } catch (err) {
    console.log(err);
    // ?️ no return value here ?️
  }
};

这里的问题是我们已经键入了返回 Promise<number> 的函数,因此 TypeScript 期望对函数的所有调用都返回 Promise<number>,即使是那些出错的调用。

要解决这个问题,请使用联合类型将函数的返回类型设置为 Promise<number | undefined>。

// ✅ Works now
const getPromise = async (): Promise<number | undefined> => {
  try {
    const result = await Promise.resolve(42);
    return result;
  } catch (err) {
    console.log(err);
  }
};

现在 TypeScript 知道该函数返回类型为 number 或 undefined 的 Promise,这是函数返回类型的准确表示。

当我们获得函数的返回值时,使用类型保护来确定它是 number 还是 undefined。

const getPromise = async (): Promise<number | undefined> => {
  try {
    const result = await Promise.resolve(42);
    return result;
  } catch (err) {
    console.log(err);
  }
};

getPromise().then((value) => {
  if (typeof value === 'number') {
    // ✅ We know that value is number
    console.log(value.toFixed());
  }
});

我们在其中使用 typeof 运算符的简单 if 语句用作类型保护。

第三个例子展示了 TypeScript 并不总是能够准确地确定函数的流程。

// ⛔  Error:️ Function lacks ending return statement
// and return type does not include 'undefined'.ts(2366)
const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  } else if ('hello'.length === 6) {
    return 'hello';
  }
  // ?️ TypeScript doesn't know that ?️
  // getting here is impossible
};

字符串 hello 的长度为 5,因此我们知道 if 块将运行并且我们将始终返回值 hello,但 TypeScript 不知道。

下面2个例子是一样的。

// ✅ Works now
const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  } else {
    return 'bye';
  }
};

或者完全删除 else 块。

// ✅ Works now

const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  }
  return 'bye';
};

无论哪种方式,TypeScript 现在都能够确定函数的所有代码路径都返回字符串类型的值。

错误的一个常见原因是 – 我们从内部函数或回调返回一个值,并认为该值也从外部函数返回。

// ⛔  Error:️ Function lacks ending return statement
// and return type does not include 'undefined'.ts(2366)
const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  }

  function inner() {
    return 'bye';
  }

  inner();
};

如果我们遇到类似情况,请确保返回调用内部函数的结果。

// ✅ Works now
const getString = (): string => {
  if ('hello'.length === 5) {
    return 'hello';
  }

  function inner() {
    return 'bye';
  }

  return inner();
};

总结

当并非具有显式返回类型的函数的所有代码路径都返回值时,会出现“Function lacks ending return statement”错误。 要解决该错误,请从所有代码路径返回一个值或在函数的返回类型中包含 undefined。