TypeScript 里的 class field
例子如下:
和这个知识点相关的 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 的访问其 accessors
class 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;
解决办法:
- 点赞
- 收藏
- 关注作者
评论(0)