我在 Angular 应用程序中遇到 Typescript 编译错误。以下是示例代码和错误消息。
请您指导我抑制此错误。我认为这段代码根据 Javascript 是正确的。
- error TS2611: 'foo' is defined as a property in class 'A', but is overridden here in 'B' as an accessor.
export class A {
foo: string;
}
export class B extends A {
f1;
set foo(name) {
this.f1 = name;
}
get foo() {
return this.f1;
}
}
编者注:在评论中发现,
A
和B
这两个类都在第三方库中。
错误消息是正确的,因为这里有一个微妙的错误。当您在父类中定义属性时,会为其每个子类自动创建该属性。
因此,在您编写的代码中,如果您不为类B编写:
set/get foo(name) { ... }
,该类将具有foo
属性无论如何,因为该属性是在B
的父类中声明的 - A
。
在您的代码中,您实际上是在使用访问器声明破坏
foo
中声明的 A
属性。
如果你想要求
A
的所有子类都声明它们的 own foo
属性(类似于接口),那么可以尝试:
export class A {
abstract foo: string;
}
另一种方法是创建一个
abstract
类,您可以使用它来扩展子类。
我使用 interface
然后使用 abstract
然后在我的最后一堂课中使用访问器(获取/设置)扩展它。
在
interface
中,您将定义您的属性。但是,如果您要使用访问器(获取/设置),则需要创建一个 abstract
。我只会在针对类存储和检索数据的数据类型类上执行此操作。
下面的示例可以在这里找到带有接口、抽象、扩展的 Typescript Playground 示例
interface IQuote {
qty: number,
rate: number | string,
total ? : number | string
}
abstract class AQuote implements IQuote {
abstract set qty(x: number);
abstract get qty(): number;
abstract set rate(x: number | string);
abstract get rate(): number | string;
abstract set total(x: number | string);
abstract get total(): number | string
protected abstract updateTotal(): void
abstract getTotalNum(): number
}
class quote extends AQuote {
constructor(obj: IQuote) {
super()
this.qty = obj.qty
this.rate = obj.rate
}
set qty(v: number) {
this._qty = v;
this.updateTotal()
}
get qty() {
return this._qty;
}
set rate(v: number | string) {
this._rate = Number(v);
this.updateTotal()
}
get rate() {
return new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP'
}).format(Number(this._rate))
}
set total(v: number | string) {
this._total = Number(v);
}
get total(): number | string {
return new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP'
}).format(Number(this._total))
}
getTotalNum() {
return Number(this._total)
}
protected updateTotal() {
this.total = Number(this._rate) * Number(this._qty)
}
private _qty: number = 1;
private _rate: number | string = 1;
private _total ? : number | string = (Number(this._rate) * this._qty);
}
class QuoteArray extends Array < quote > {
getTotals(): number {
let totalFigure: number = 0
this.forEach(o => {
totalFigure = totalFigure + o.getTotalNum()
});
return totalFigure
}
}
let arry: QuoteArray = new QuoteArray();
arry.push(new quote({
qty: 2,
rate: 5
}))
arry.push(new quote({
qty: 3,
rate: 5
}))
arry.push(new quote({
qty: 3,
rate: 5
}))
arry.push(new quote({
qty: 3,
rate: 5
}))
arry.push(new quote({
qty: 3,
rate: 5
}))
console.log(arry);
console.log(arry.getTotals())
上面的示例创建了一个引号数组,我可以像数组一样操作它,但我还扩展了数组类型以提供名为
getTotals()
的方法,以便它打印出格式化的货币。
这是编程语言中的常见行为,当您从父级继承时,您不能使用相同的变量/函数/访问器名称,直到您指定新名称覆盖旧名称,但始终必须是相同的类型。因此,在您的示例中,我们在父级中有变量,在子级中有访问器。您可以进行此更改:
class A {
_foo: string = "";
set foo(name) {
this._foo = name;
}
get foo() {
return this._foo;
}
}
export class B extends A {
f1: any;
set foo(name) {
this.f1 = name;
}
get foo() {
return this.f1;
}
}
我相信有某种方法可以省略类型限制(如果必须的话),但我不知道如何做,我认为这不是好方法(程序应该对读者来说很清楚)。
正如有人已经发布的,这是 TS 4 中新强制执行的错误检查(请参阅此处)
但是,由于您完全处理第三方库,因此您的解决方案可能仅限于以下选项:
似乎在某些情况下您无法禁用此错误。
“Typescript 无法区分 d.ts 中的属性和访问器”
您可以关注以下讨论:https://github.com/microsoft/TypeScript/issues/41347
2022/05/31 修复/合并;但尚未发布 [截至 [电子邮件受保护]]
为了抑制我添加的警告,
"skipLibCheck": true,
到我的 tsconfig.json
这告诉 TypeScript 跳过检查第三方库中的类型,它解决了我的问题。
它也比我在这里读到的其他解决方案容易得多。
这是完整的 tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "ES2017",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"strict": false,
"skipLibCheck": true,
},
"lib": ["ES2017"]
}