首页 > 解决方案 > 为类对象赋值后出现“TypeError:XXXX 不是函数”

问题描述

假设我们在 Typescript 中有一个类:

class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet() {
    return "Hello, " + this.greeting;
  }
}

现在,如果你这样做:

let greeter = new Greeter('World');
greeter.greet();

一切正常。

但是,如果您这样做:

let greeter = {greeting: 'World'};
greeter.greet();

它抛出一个错误:

ERROR TypeError: greet is not a function

现在,我知道是什么导致了这个错误。它是一个普通对象,它被分配给类对象并且不知道 greet() 是什么。即使我对对象进行类型转换,错误也不会消失。

let greeter = {greeting: 'World'} as Greeter;

我通过在我的类中放置一个静态函数来解决这个问题,如下所示:

public static fromObject(greeter: Greeter) {
  return new Greeter(greeter.greeting);
}

所以,我在这里有两个问题:

  1. 这是一个错误吗?
  2. 有没有更好的方法来解决这个问题?

(我有一个普通对象开始的原因是我从 Web 服务接收它。)

标签: typescript

解决方案


即使我对对象进行类型转换,错误也不会消失。

类型断言(它们没有强制转换)对对象没有任何影响。在那里添加类型断言所做的只是让 TypeScript 认为对象是 aGreeter而不是。

  1. 这是一个错误吗?

不在 TypeScript 或 JavaScript 中,不。

  1. 有没有更好的方法来解决这个问题?

如果您有一个具有要从中创建的属性(可能还有其他属性)的非对象,那么您fromGreeter是一种合理的方法来处理它(尽管类型注释应该是object,而不是) 。或者您可能会重载构造函数,以便它接受一个普通对象并复制属性。GreeterGreetergreetingGreeter

如果您想相信普通对象只会具有应在欢迎程序上的有效属性,您可以使用Object.assign将它们复制到新实例:

public static fromObject(greeter: object): Greeter {
  return Object.assign(new Greeter(), greeter);
}

如果我没有说可以(从 ES2015 开始)更改对象的原型,那我就是失职了,但不建议这样做并且会影响性​​能。因此,可以使用以下方法将现有的普通对象实际转换为某种东西Greeter.prototype

// Not recommended, but possible
Object.setPrototypeOf(plainObject, Greeter.prototype);

就像您一样,创建一个新实例并将属性复制到它几乎总是更好fromObject


推荐阅读