typescript 如何设置原型类字段?

lb3vh1jj  于 2023-01-14  发布在  TypeScript
关注(0)|答案(2)|浏览(178)

在vanilla JavaScript中,设置类的原型字段很容易:

class Bird {
  static {
    this.prototype.canFly = true;
  }
}
new Bird().canFly // true

然而,在TypeScript中,编译器会抱怨该属性不存在,我们可以用@ts-ignore标记错误行,这样就可以工作,但这样我们就失去了对该字段的智能感知和类型检查。
此外,我们不能显式声明class字段,因为这样我们就需要初始化该字段,这就违背了建立原型的目的。

class Bird {
  canFly: boolean; // Property 'canFly' has no initializer and is not definitely assigned in the constructor.ts(2564)
  static {
    this.prototype.canFly = true;
  }
}

即使我们对它进行@ts-ignore,该字段仍然使用undefined进行初始化,只是为了显式声明。

class Bird {
  // @ts-ignore
  canFly: boolean;
  static {
    this.prototype.canFly = true;
  }
}

new Bird().canFly; // undefined

我也尝试过使用declare关键字"外部"声明字段,但也是不可能的:

class Bird { // Duplicate identifier 'Bird'.ts(2300)
  static {
    this.prototype.canFly = true;
  }
}

declare class Bird { // Duplicate identifier 'Bird'.ts(2300)
  canFly: boolean;
}

有没有一种TypeScript方法可以声明字段存在,而不必在示例中初始化它?

wswtfjt7

wswtfjt71#

Typescript不擅长输入传统的prototype模式。
也就是说,还有一些变通办法。
有没有一种TypeScript方法可以声明字段存在,而不必在示例中初始化它?
是的,使用declare

class Bird {
  declare canFly: boolean

  clipWings() {
    this.canFly = false
  }
}

Bird.prototype.canFly = true

其编译为:

class Bird {
    clipWings() {
        this.canFly = false;
    }
}
Bird.prototype.canFly = true;

并按照您的期望:

const wildBird = new Bird()
console.log(wildBird.canFly) // true

const cagedBird = new Bird()
cagedBird.clipWings()
console.log(cagedBird.canFly) // false

// only the instance got clipped
console.log(wildBird.canFly) // true

declare是一个仅限类型的构造,并告诉Typescript假装它存在。
因此,您declarecanFly属性,现在不必向编译器证明该属性存在。
见Playground

    • 重要提示:**declare不是类型安全的,因为它只是在使用时假装一个值存在。如果误用,这可能会导致严重的类型安全问题。在生产代码中几乎不要使用它。
nue99wik

nue99wik2#

Alex Wayne在这方面客观上是正确的,我只想强调他回答的一部分。

declare is a type only construct, and tells Typescript to pretend that this exists.

declare是一个非常有用但非常危险的关键字。它可以让你的东西编译得很好,但实际上可能会在运行时破坏东西。我个人只建议当你试图在TS代码中采用一个旧的、经过测试的JS库时使用它。
declare就像在说:“假设这是真的。即使不是,也要假设它是真的。”使用时要非常谨慎;因为几乎总是有更好的解决办法。

相关问题