允许从抽象 class 继承到 return 未定义的 class

Allowing a class that inherits from an abstract class to return undefined

我有一个摘要 class 看起来像这样:

// step.ts

import { AllowedStepNames } from "./interfaces"; 

abstract class Step {
  abstract nextStep(): AllowedStepNames | undefined
}

这又在单独的文件中使用了一个类型:

// interfaces/index.ts

const stepList = {
  foo: "bar",
  bar: "baz"
};

export type AllowedStepNames = keyof typeof stepList;

我有一个从它延伸出来的 class,看起来像这样:

// referral-reason.step.ts

export default class ReferralReasonStep extends Step {
  nextStep() {
    return this.params.reason === 'no-reason' ? 'foo' : undefined
  }
}

但是,编译器抛出错误:

Property 'nextStep' in type 'NotEligibleStep' is not assignable to the same property in base type 'Step'.

但是,如果我像这样在继承的 class 中添加 return 类型:

export default class ReferralReasonStep extends Step {
  nextStep(): AllowedStepNames | undefined {
    return this.params.reason === 'no-reason' ? 'foo' : undefined
  }
}

这对我来说似乎很奇怪,因为我希望扩展 class 从抽象 class 继承 return 类型。有人能告诉我这是怎么回事吗?还是我做错了什么?

此外,如果我将所有 classes 和类型放在同一个文件中,问题就会消失。

Reproducable example here

我想我现在找到问题了:

TypeScript 会根据 return 类型自动将类型 string 而不是 foo | undefined 推断给您的函数,并且 string 不可分配给联合 AllowedStepNames.

你能做些什么来解决这个问题?

选项 1

正如您在 post 中所说,您可以将函数的 return 类型显式设置为 foo | undefined

选项 2

TypeScript playground 中没有错误的原因是 tsconfig 规则不同。我确定 strictNullChecks 是改变这种行为的规则。因此,根据您的项目,您可以启用此规则。

compilerOptions: {
  strictNullChecks: "true"
}

选项 3

通过使用 as const,您可以告诉编译器使用字符串文字值作为类型,而不是 string

nextStep() {
  return this.params.reason === "no-reason" ? "foo" as const : undefined;
}