严格模式本身不直接提供类属性硬性约束,真正的硬性约束来自typescript类型系统与严格模式协同作用;启用strict mode是起点,ts的strictpropertyinitialization要求非可选实例属性必须在声明时或构造函数中初始化,否则编译报错。

严格模式本身不直接提供“类属性硬性约束”能力,但它为这类约束创造了必要前提——让类型系统真正生效,从而让编译器能强制你初始化、校验、不可绕过地处理类成员。真正的硬性约束来自类型系统(如 TypeScript)与严格模式协同作用,而非 JavaScript 原生 strict mode 单独实现。
启用严格模式是硬性约束的起点
TypeScript 的 "strict": true 会同时激活包括 strictNullChecks、strictPropertyInitialization 在内的八大检查。其中 strictPropertyInitialization 就是类属性硬性约束的核心开关:
- 它要求所有非可选(non-optional)、非 undefined 类型的实例属性,必须在构造函数中显式赋值,或在声明时提供初始值;
- 否则编译直接报错:
Class 'User' incorrectly implements interface 'IUser'. Property 'name' has no initializer and is not definitely assigned in the constructor.
用类型定义 + 构造函数强制初始化实现硬性约束
不是靠运行时拦截,而是靠编译期锁定。例如:
class User {
id: number; // ❌ 编译失败:未初始化
name: string; // ❌ 同上
email?: string; // ✅ 可选属性,允许未赋值
role: "admin" | "user" = "user"; // ✅ 有默认值,满足约束
constructor(id: number, name: string) {
this.id = id; // ✅ 在构造函数中赋值
this.name = name; // ✅ 同上
}
}
这种写法下,任何遗漏初始化的字段都会被 TS 拦在编译阶段,无法生成 JS —— 这才是真正的“硬性”。
结合 readonly + 构造器参数简写进一步加固
避免属性被意外修改,同时收口赋值入口:
class Order {
constructor(
public readonly id: number,
public readonly amount: number,
private _status: "pending" | "done" = "pending"
) {
if (amount
- public readonly id:字段只读、必须由构造器传入、不可后期篡改;
- 所有业务校验(如金额合法性)放在构造器内,确保对象一旦创建,状态即合法;
- 没有 setter、没有空构造、没有字段延迟赋值——边界清晰,无侥幸空间。
配合非空断言与明确类型收窄增强可靠性
当某些字段必须存在但无法在构造器中立即赋值(如异步初始化),可用非空断言(!)配合明确类型,但需辅以运行时保障:
class ApiClient {
baseUrl!: string; // 允许延后赋值,但类型系统仍要求你明确“它一定不为空”
init(config: { url: string }) {
if (!config.url) throw new Error("baseUrl 不能为空");
this.baseUrl = config.url;
}
}
注意:! 是对编译器的“承诺”,不是运行时保护。所以必须搭配手动校验(如 throw)或初始化逻辑,否则仍是风险点。
不复杂但容易忽略:硬性约束不是写个注释或文档说明,而是让编译器替你盯住每一行代码。开启 strict,用好 strictPropertyInitialization 和 readonly,再把校验逻辑塞进构造器——这才是防御性编程在类设计层面最扎实的落地方式。











