【问题标题】:Using instanceof in TypeScript to find return type of function results in "refers to a type, but is being used as a value here"在 TypeScript 中使用 instanceof 查找函数的返回类型会导致“引用类型,但在此处用作值”
【发布时间】:2020-05-16 19:05:47
【问题描述】:

我正在使用 TypeScript,并且遇到一个函数返回两种类型的联合的情况。它可以返回字符串或模型,但我不知道如何获取类型并根据返回的类型执行操作。

我该怎么做这样的事情? 在此示例中如何将字符串和 IMyModel 用作值(如错误消息所示)?这个错误让我感到困惑。

export interface IMyModel {
  id: number;
  name: string;
}

const myFunc = (value: boolean): string | IMyModel => {
  if (value) return "a string";

  return {
    id: 12,
    name: "model",
  };
};

const a = myFunc(true);

if (a instanceof string) {
  console.log("it is a string");
}

if (a instanceof IMyModel) {
  console.log("it is a model");
}

我在使用 instanceof 的行中的 Visual Studio 代码中出现以下静态错误:

'string' 仅指一种类型,但在此处用作值。ts(2693)

'IMyModel' 仅指一种类型,但在此处用作值。ts(2693)

我也将界面切换为使用“类型”,但还是一样。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    Typescript 是 javascript 的超集,最终编译为 javascript。话虽如此,重要的是要考虑您正在编写的代码在 javascript 中的样子。 Here is what this will look like compiled

    const myFunc = value => {
      if (value) return "a string";
      return {
        id: 12,
        name: "model"
      };
    };
    const a = myFunc(true);
    if (a instanceof string) {
      console.log("it is a string");
    }
    if (a instanceof IMyModel) {
      console.log("it is a model");
    }
    
    

    你会注意到你声明的类型被编译掉了。这个错误现在开始变得更有意义了。我们不能在 typescript 类型上调用 instanceof,因为就编译的 javascript 而言,它们不存在。您可能正在寻找:

    typeof type guards

    if (typeof a === 'string') {
      console.log("it is a string");
    }
    

    User defined type guards:

    const isMyModel = (model: any): model is IMyModel => {
      return typeof model === 'object' && Boolean(model.id && model.name)
    }
    if (isMyModel(a)) {
      console.log("it is a model");
    }
    

    或两者兼而有之!

    【讨论】:

    • a instanceof String 不起作用。 'foo' instanceof Stringfalse
    • 我们真的可以在普通的旧 JS 中使用instanceof 来检查类型吗?我不确定为什么 'foo' instanceof String 会失败。
    • 最好的 javascript SO 引用此答案之一:stackoverflow.com/a/203757/7165303“记住这样的事情的简单方法是问自己“我想知道什么是理智和容易学习的”?无论答案是什么是,Javascript 做另一件事。”
    【解决方案2】:

    要检查某个内容是否为字符串,您可以使用与 JavaScript 中相同的方式进行操作

    if (typeof a === "string")
    

    接口纯粹是一种 TypeScript 结构,不存在于转译的 JavaScript 中。由于它是一个联合,因此您可以假设如果它不是字符串,则它必须是 IMyModel

    【讨论】:

      【解决方案3】:

      object instanceof constructor 表达式中的右手参数应该是构造函数/函数。

      instanceof 运算符测试constructor.prototypeobject 的原型链中是否存在。

      更多信息here


      回到你的例子。一种可能的解决方案是测试typeof a 是否为'string'

      if (typeof a === 'string') {
        a // a is of type string here
        console.log("it is a string");
      } else {
        a // a is IModel
        console.log("it is a model");
      }
      

      Playground

      More 在 typeof 类型保护上

      【讨论】:

        猜你喜欢
        • 2020-09-15
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 2016-03-31
        • 1970-01-01
        • 2018-09-05
        • 1970-01-01
        • 2023-02-15
        相关资源
        最近更新 更多