将值分配给类对象后,出现“ TypeError:XXXX不是函数”

时间:2018-10-22 09:51:03

标签: typescript

比方说,我们在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服务接收到的。)

1 个答案:

答案 0 :(得分:3)

  

即使我强制转换对象,错误也不会消失。

Type assertions(它们不是强制转换)对对象没有任何影响。在那里添加类型断言的所有事情都是使TypeScript认为对象不是Greeter

  
      
  1. 这是一个错误吗?
  2.   

不是在TypeScript或JavaScript中,

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

如果您有一个非fromGreeter对象,并且您的object对象是一个合理的方法(尽管类型注释应为Greeter,而不是Greeter),您要用来创建greeting的{​​{1}}属性(以及其他属性)。或者,您可能会重载构造函数,使其接受纯对象并复制属性。

如果您希望普通对象仅具有应在问候者上显示的有效属性,则可以使用Greeter将其复制到新实例:

Object.assign

如果我不说更改对象原型是可能(从ES2015起)的话,我会很失落,但是不建议这样做,它会影响性能。因此,可能会使用public static fromObject(greeter: object): Greeter { return Object.assign(new Greeter(), greeter); } 将现有的普通对象实际转换为某种东西,这是可能的

Greeter.prototype

就像您的// Not recommended, but possible Object.setPrototypeOf(plainObject, Greeter.prototype); 一样,创建新实例并将属性复制到它几乎总是更好。