如何让老式课程在打字稿中起作用?

时间:2018-04-12 14:29:21

标签: typescript ecmascript-5

在将大量文件转换为typescript时,我有很多类以这种方式声明。

function FooClass() {
    this.bar = 1; // error TS2683: 'this' implicitly has type 'any'
                  // because it does not have a type annotation.
}

FooClass.prototype.myMethod = function() {
    // ...
}

如何在启用严格类型检查的情况下完成此工作,同时避免使用类语法重写所有内容?

3 个答案:

答案 0 :(得分:6)

让上述代码工作的最简单方法是向函数添加this parameter,如下所示:

function FooClass(this: {bar: number}) {
    this.bar = 1; // okay
}

不幸的是,当您将其视为构造函数时,您很快就会发现编译器不知道如何处理FooClass

const oops = new FooClass(); // error, oops is implicitly any
oops.bar // okay but compiler has no idea
oops.myMethod() // okay but also no idea
oops.foo // also okay, but you probably don't want it to be
oops.yourMethod() // ditto

这显然是by design。在我看来,注释这一点的最好方法是提前定义类型FooClassFooConstructor

interface FooClass {
  bar: number;
  myMethod(): void;
}

interface FooConstructor {
  new(): FooClass,
  prototype: FooClass
}

请注意,当您使用class FooClass {}创建构造函数的方式时,TypeScript会自动生成 FooClass,它是构造函数本身,以及类型< / em> FooClass这是构造函数创建的实例的类型。这通常会让开发人员感到困惑,所以要小心。我们手动执行此操作:上面的interface FooClass类型,而不是我们即将创建的

定义这些类型后,在创建FooClass函数时声明FooConstructor函数的类型为Function(断言需要通过anyconst FooClass = function FooClass(this: FooClass) { this.bar = 1; } as Function as FooConstructor; FooClass.prototype.myMethod = function () { // ... } 并且不安全,所以要小心)。

const okay = new FooClass();
okay.bar // number
okay.myMethod() // known
okay.foo // error, yay
okay.yourMethod() // error, yay

并测试出来:

Worksheets("Res_Kontor").Range("M:N").Value = res

希望有所帮助;祝你好运!

答案 1 :(得分:1)

如果您不想转换它们,我建议将它们保存为JavaScript文件,并为它们编写声明文件。然后TypeScript会隐式识别它们,而不会重写代码。

您可以向项目添加types.d.ts文件并:

declare class FooClass {
    public bar: number;
    public myMethod: () => void;
    ...
}

在项目中使用此类文件,TypeScript将允许您执行const myClass = new FooClass();

当然,您仍然需要添加JavaScript代码(或者您将遇到运行时错误),并以适合您的方式导入它。如果您使用的是全局文件,则可以将它们加载到页面中,或者在您正在处理的任何环境中使用。如果您的旧代码在模块中,则在需要使用它们时导入这些模块。

答案 2 :(得分:0)

我注意到TypeScript v3.6.2在.js文件的上下文中的行为似乎有所不同。幸运的是,以下ECMAScript 5样式类似乎是类型推断的,并且检测到了两种预期的类型错误:

/**
 * @class Person
 * @param {string} name
 */
function Person(name) {
  this.name = name
}

var person = new Person("John")
person.foo // TS2339: Property 'foo' does not exist on type 'Person'.
person.name

new Person(42) // Argument of type '42' is not assignable to parameter of type 'string'.

这可以通过以下方式确认:

$ tsc --checkJs --allowJs --noImplicitAny --strictNullChecks test.js

因此,返回到.js文件可能是继续原始继承样式的一种方法。

但是,对于子类,此方法似乎无效。我已将详细信息发布到https://github.com/microsoft/TypeScript/issues/18171