在将大量文件转换为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() {
// ...
}
如何在启用严格类型检查的情况下完成此工作,同时避免使用类语法重写所有内容?
答案 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。在我看来,注释这一点的最好方法是提前定义类型FooClass
和FooConstructor
:
interface FooClass {
bar: number;
myMethod(): void;
}
interface FooConstructor {
new(): FooClass,
prototype: FooClass
}
请注意,当您使用class FooClass {}
创建构造函数的方式时,TypeScript会自动生成值 FooClass
,它是构造函数本身,以及类型< / em> FooClass
这是构造函数创建的实例的类型。这通常会让开发人员感到困惑,所以要小心。我们手动执行此操作:上面的interface FooClass
是类型,而不是我们即将创建的值。
定义这些类型后,在创建FooClass
函数时声明FooConstructor
函数的类型为Function
(断言需要通过any
或const 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。