例子如下: 和这个知识点相关的 tsc 编译选项:strictPropertyInitialization strictPropertyInitialization 设置控制是否需要在构造函数中初始化类字段。 正确做法: class GoodGreeter { name: string; constructor() { this.name = "hello"; } } 请注意,该字段需要在构造函数本身中进行初始化。 TypeScript 不会分析您从构造函数调用的方法来检测初始化,因为派生类可能会覆盖这些方法并且无法初始化成员。 class 成员需要在构造函数里进行初始化操作。如果在构造函数里调用其他函数,然后在这些其他函数里进行字段初始化,这样也不行。 如果一定要这样做,即您打算通过构造函数以外的方式明确初始化字段(例如,可能外部库正在为您填充类的一部分),您可以使用明确赋值断言运算符,!: class OKGreeter { // Not initialized, but no error name!: string; } 如果一个 class field 设置为 readonly,这表示它只能在构造函数内被赋值。 子类构造函数的第一行语句,必须是 super() 函数调用; 什么是 TypeScript class 里的成员方法准确定义:A function property on a class is called a method. 除了标准类型注解之外,TypeScript 不会向方法添加任何其他新内容。 需要注意的是,在 TypeScript 方法实现内部,必须用 this. 来访问其成员变量。 下列代码里,m 方法内部,访问的是 class 外部定义的类型为 number 的 x 变量,而不是 class 内部类型为 string 的变量。 let x: number = 0; class C { x: string = "hello"; m() { // This is trying to modify 'x' from line 1, not the class property x = "world"; Type 'string' is not assignable to type 'number'.Type 'string' is not assignable to type 'number'. } } class 的访问其 accessorsclass C { _length = 0; get length() { return this._length; } set length(value) { this._length = value; } } TypeScript 对访问器有一些特殊的推理规则: (1)如果get存在但没有set,则该属性自动为只读 (2)如果没有指定setter参数的类型,则根据getter的返回类型推断 (3)Getter 和 setter 必须具有相同的成员可见性 关于 TypeScript class 继承和接口实现的一些坑重要的是要理解implements 子句只是检查类是否可以被视为接口类型。 它根本不会改变类的类型或其方法。 一个常见的错误来源是假设一个implements 子句会改变类的类型——它不会! 看这个例子: interface Checkable { check(name: string): boolean; } class NameChecker implements Checkable { check(s) { // Notice no error here return s.toLowerCase() === "ok"; } } const a = new NameChecker(); console.log(a.check('ok')); 语法错误: 原因是因为第 6 行代码里,我们没有为 check 方法的参数 s 指明类型,因此其类型默认为 any. 这就和 interface Checkable 里定义的 check 方法的输入参数类型 string 不一致了。 解决办法: 同样,使用可选属性实现接口不会创建该属性: interface A { x: number; y?: number; } class C implements A { x = 0; } const c = new C(); c.y = 10; 解决办法: |
|