【问题标题】:'new' expression, whose target lacks a construct signature in TypeScript'new' 表达式,其目标在 TypeScript 中缺少构造签名
【发布时间】:2017-04-26 01:23:26
【问题描述】:

我们有以下TestComponent.ts TypeScript 类:

01: import TestVectorLayer from './TestVectorLayer'
02: 
03: export class TestComponent implements OnInit {
04:   private foo: any;
05: 
06:   constructor() { }
07: 
08:   const layer = new TestVectorLayer("foo");
09: }

还有下面的TestVectorLayer.ts函数:

请记住,OpenLayer 3 使用的是 Google Closure Library,这就是为什么 TestVectorLayer 不是 TypeScript 类。

01: declare let ol: any;
02:
03: const TestVectorLayer = function (layerName: string) {
04:   ...
05:   console.log(layerName);
06:
07:   ol.layer.Image.call(this, opts);
08: }
09:
10: ol.inherits(TestVectorLayer as any, ol.layer.Image as any);
11:
12: export default TestVectorLayer; 

我们收到以下错误:

Error on Line 08 in TestComponent.ts class:

[ts] 'new' 表达式,其目标缺少构造签名,隐含地具有 'any' 类型。 导入TestVectorLayer

package.json 版本的 TypeScript:

开发依赖:

"typescript": "~2.2.1"

【问题讨论】:

  • 如果你想new 它为什么不能TestVectorLayer 是一个类?
  • @Saravana 这应该没关系,归根结底,课程只是语法糖。
  • @AluanHaddad 我已经更新了这个问题。 TestVectorLayer 正在使用 OpenLayer 3,它使用 Google Closure Library。
  • @fuzz 所以你使用的是--allowJs?我仍然有点困惑,因为如果它是第三方库,你为什么要从相对路径中使用它,而不是从带有 package.json 和许可证文件的包中使用它?
  • @Saravana 确实,上课不会有什么坏处。只是为了打字的好处。

标签: javascript typescript


【解决方案1】:

David 的回答很好,但如果您只想快速编译它(例如,因为您正在从 JS 迁移到 TS),那么您可以简单地将 any 放在那里,让抱怨的编译器闭嘴。

TS 文件:

const TestConstructorFunction = function (this: any, a: any, b: any) {
    this.a = a;
    this.b = b;
};

let test1 = new (TestConstructorFunction as any)(1, 2);

编译成这个JS文件:

var TestConstructor = function (a, b) {
    this.a = a;
    this.b = b;
};
var test1 = new TestConstructor(1, 2);

注意不要犯这个错误:

TS 文件:

// wrong!
let test2 = new (TestConstructorFunction(1, 2) as any);

JS结果:

// wrong!
var test2 = new (TestConstructor(1, 2));

这是错误。你会在运行时收到TypeError: TestConstructor(...) is not a constructor 错误。

【讨论】:

  • 我正在从非常旧的 JS 迁移,这对我来说是正确的答案。
  • 非常感谢,它有效! const s1 = new (Student as any)('elite', 23);
  • 拯救了我的一天!我需要让它适用于我没有写过的课程
  • 所以这个利基答案比正确的答案获得了更多的喜欢。这有点令人担忧,因为新手可能会认为这是一种正常的方法。是作弊,比@ts-ignore好一点。
  • @Onkeltem 是的,我也很惊讶它得到了更多的喜欢。好吧,人们想要修复编译器错误并继续前进。我不能责怪他们。我想这总比不使用 Typescript 好 ;-) 接受的答案显然更好,因为它为函数提供了正确的类型定义,因此在所有 new FunCtr(...) 调用中都进行了类型检查。但是,如果您只需要修复一个调用它的地方,那么我认为这没什么大不了的。使用as any 的 IMO 通常应被视为不好的做法,但有时您只想关闭编译器并继续...
【解决方案2】:

这是问题的简化:

const TestVectorLayer = function(layerName: string) {
};

const layer = new TestVectorLayer("");

发生错误是因为TestVectorLayer 没有新的签名,所以layer 被隐式键入为any--noImplicitAny 的错误。

您可以通过切换到一个类来解决此问题,但在您的情况下,这似乎有点复杂,因为继承是由底层框架完成的。因此,您将不得不做一些更复杂的事情,这并不理想:

interface TestVectorLayer {
  // members of your "class" go here
}

const TestVectorLayer = function (this: TestVectorLayer, layerName: string) {
  // ...
  console.log(layerName);
  ol.layer.Image.call(this, opts);
} as any as { new (layerName: string): TestVectorLayer; };

ol.inherits(TestVectorLayer, ol.layer.Image);

export default TestVectorLayer; 

然后在文件中用TestComponent:

const layer = new TestVectorLayer(layerName); // no more compile error

【讨论】:

  • 您的更复杂但不理想的解决方案有效。 :) 感谢您提供临时修复。我们将尝试切换到一个类。最初我们切换到一个类,发现继承存在一大堆问题,所以我们采用了 JS 和 TS 注释的混合方法。
  • @fuzz 没问题!可能有更好的方法……只是暂时想不到。
  • @DavidSherret 你能分享我在哪里可以获得更多关于as any as的信息/文档
  • @SohelAhmedM 了解类型断言hereas any 是对 any 类型的类型断言。执行value as any as T 是两种类型断言,并且是一种在value 的类型不能断言为T 时将value 的类型断言为T 的方法(例如,当value as T 会导致编译错误时,但你想以任何方式断言它)。本质上,这是一种绕过类型检查器的方法。
  • 喜欢打字稿。花了多少时间试图弄清楚这些东西?
【解决方案3】:

就我而言,例如,您必须将其定义为 any 并具有 new 签名。

const dummyCtx = function(txt: string) {
  this.foo = txt
} as any as { new (txt: string): any }

// just use it as usual
const dctx = new dummyCtx('bar')

【讨论】:

【解决方案4】:

我会给你的 TestVectorLayer 一个接口

class TestVectorLayer implements TestVectorLayer {
    
}

interface TestVectorLayer {
    new (layerName: string): TestVectorLayer;
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-22
    • 2018-02-06
    • 2022-01-19
    • 2020-04-12
    • 1970-01-01
    • 2017-03-25
    • 2017-01-29
    • 1970-01-01
    相关资源
    最近更新 更多