tsconfig.json strict属性配置false会有什么响

当你在 tsconfig.json 中将 "strict": false 时,TypeScript 会关闭一组"严格类型检查"规则。这样虽然可以更快上手、减少编译报错,但也会让更多潜在的运行时错误躲过编译期,降低代码可维护性和重构安全性。

下面先解释 strict 的概念与包含的子选项,再通过通俗示例展示关闭 strict 可能带来的问题,以及相应的"正确写法"。

strict 是什么?

在 TypeScript 中,"strict": true 会一次性启用一组严格相关的检查选项(具体集合随 TS 版本略有变化,一般包括):

  • "noImplicitAny":禁止隐式的 any
  • "strictNullChecks":严格区分可能为 null/undefined 的值。
  • "strictFunctionTypes":更严格地检查函数类型参数的协变/逆变。
  • "strictBindCallApply":严格检查 call/apply/bind 的参数类型。
  • "strictPropertyInitialization":类的实例属性必须初始化或在构造函数中赋值。
  • "useUnknownInCatchVariables"catch (e) 中的 e 默认为 unknown,需要显式缩小或断言。
  • "noImplicitThis":禁止隐式的 this:any
  • "alwaysStrict":编译后的 JS 使用严格模式("use strict"),非模块脚本场景更明显。

注意:

  • 有些常用但不在 strict 集合内的"更严"选项(如 "noUncheckedIndexedAccess""exactOptionalPropertyTypes")需要手动单独开启。
  • 严格集合可能随 TS 版本演进略有增减,以本地 TypeScript 版本文档为准。

关闭 strict 的总体影响

  • 更多隐式的 any 混入,类型信息丢失,重构风险上升。
  • null/undefined 不再被严格检查,出现空指针类错误的概率增加。
  • 函数的参数与回调更容易"误配",问题延迟到运行时才爆炸。
  • 类的属性可能未初始化即被访问,导致不可预期的 undefined
  • catch (e) 直接当成 any 使用,降低异常处理的安全性与可读性。
  • 运行时严格模式的约束(在非模块脚本里)可能缺失,某些 this 绑定问题更隐蔽。

常见场景与示例

以下示例中的"错误示例"指的是:strict 关闭时能编译通过、但存在潜在运行时风险或类型不安全;"正确示例"是符合 strict 的写法或修复方式。

1、noImplicitAny:隐式 any

错误示例(strict 关闭时编译通过,风险大):

sql 复制代码
function add(a, b) {
  // a 和 b 被推断为 any,"数字相加"变成了"任意拼接"
  return a + b;
}

add(1, "2"); // 运行结果是 "12",并非 3

正确示例(显式标注或提供默认值/约束):

less 复制代码
function add(a: number, b: number) {
  return a + b;
}

add(1, 2); // 3

参考:

2、strictNullChecks:空值检查

  • 作用:将 null、undefined 从所有类型中分离出来,必须显式处理"可能为空"的情况。
  • 影响:开启后可显著减少空指针错误,但需要在代码中做空值校验或使用可选链等。

错误示例

typescript 复制代码
function greet(name: string) {
  // 如果实际传的是 undefined,这里会在运行时报错
  console.log(name.toUpperCase());
}

greet(undefined as any); // 运行期 TypeError

正确示例(显式包含可能的空值并做保护):

javascript 复制代码
function greet(name: string | undefined) {
  if (!name) {
    console.log("Hello, stranger!");
    return;
  }
  console.log(name.toUpperCase());
}

或改为不允许空值

scss 复制代码
function greet(name: string) {
  console.log(name.toUpperCase());
}

// 调用方自己保证非空
greet("Alice");

参考:

3、 strictPropertyInitialization:属性初始化

错误示例(strict 关闭时编译通过,但属性为 undefined):

typescript 复制代码
class User {
  name: string; // 未初始化
  constructor() {
    // 忘了给 name 赋值
  }
}

const u = new User();
u.name.toUpperCase(); // 运行期 TypeError

正确示例(在声明处或构造函数中初始化,或使用确定赋值断言):

typescript 复制代码
// 方式一:声明处初始化
class User {
  name: string = "anonymous";
}

// 方式二:构造函数中初始化
class User2 {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

// 方式三:确定赋值断言(慎用,需要你自己保证在使用前已赋值)
class User3 {
  name!: string;
  init(name: string) {
    this.name = name;
  }
}

参考:

www.typescriptlang.org/tsconfig/#s...

4、strictBindCallApply:call/apply 的参数检查

错误示例(strict 关闭时编译通过,运行期可能异常):

typescript 复制代码
function sum(a: number, b: number): number {
  return a + b;
}

sum.call(null, 1, "2" as any); // 编译不报错,但语义错误

正确示例(严格匹配参数类型):

typescript 复制代码
function sum(a: number, b: number): number {
  return a + b;
}

sum.call(null, 1, 2); // OK

参考:

www.typescriptlang.org/tsconfig/#s...

5、strictFunctionTypes:函数类型的参数检查更严格

错误示例(strict 关闭时可能被接受,存在类型不安全):

typescript 复制代码
interface Animal { name: string }
interface Dog extends Animal { bark(): void }

type Handler = (a: Animal) => void;

// 将参数更"窄"的函数赋给更"宽"的函数类型(不安全)
const handleDog: (d: Dog) => void = d => d.bark();

// 在 strictFunctionTypes 关闭时,这样的赋值可能被允许
const h: Handler = handleDog;

// 运行时:如果传入的是普通 Animal 而非 Dog,会出错
const justAnimal: Animal = { name: "Tom" };
h(justAnimal as any); // 运行期可能调用 bark() 报错

正确示例(使用恰当的参数范围或做类型保护):

javascript 复制代码
const handleAnimal: Handler = a => {
  // 若需要 Dog 的行为,先做类型缩小
  if ((a as Dog).bark) {
    (a as Dog).bark();
  } else {
    console.log(a.name);
  }
};

或改变设计:将"输出协变、输入逆变"的原则体现到类型中,避免将"窄参数函数"赋给"宽参数函数"。

参考:

www.typescriptlang.org/tsconfig/#s...

6、useUnknownInCatchVariables:异常类型安全

错误示例(strict 关闭时 e 是 any,使用随意):

javascript 复制代码
try {
  throw new Error("oops");
} catch (e) {
  // e 是 any,随意访问属性,潜在不安全
  console.log(e.message.toUpperCase());
}

正确示例(将 e 视为 unknown,先缩小/断言):

javascript 复制代码
try {
  throw new Error("oops");
} catch (e) {
  if (e instanceof Error) {
    console.log(e.message.toUpperCase());
  } else {
    console.log("Unknown error", e);
  }
}

参考:

www.typescriptlang.org/tsconfig/#u...

7、noImplicitThis:避免 this:any

错误示例(strict 关闭时不报错,运行期 this 可能是 undefined 或全局对象):

javascript 复制代码
function getX() {
  // 在非严格模式下,独立调用时 this 可能指向全局;在严格模式下为 undefined
  return (this as any).x;
}

const obj = { x: 42, getX };
const fn = obj.getX;

console.log(fn()); // 结果依赖调用环境,容易出错

正确示例(显式 this 类型或用箭头函数绑定):

javascript 复制代码
function getX(this: { x: number }) {
  return this.x;
}

const obj = { x: 42, getX };
console.log(obj.getX()); // 42

或者:

ini 复制代码
const obj2 = {
  x: 42,
  getX: () => 42, // 不依赖 this
};

参考:

www.typescriptlang.org/tsconfig/#n...

8、alwaysStrict:输出严格模式

在非模块脚本中,关闭 strict 也可能意味着编译产物不含 "use strict"。这会影响诸如 this 的指向、静默失败等行为,增加与运行时相关的隐患。使用模块(ESM/CJS)时通常天然是严格模式,但仍建议开启 alwaysStrict 以保持一致性。

什么时候可以考虑关掉 strict?

  • 原有 JavaScript/TS 项目体量大、类型债务多,短期无法一次性治理。
  • 第三方声明文件质量参差、阻塞开发进度时,临时"松绑"。

即便如此,也建议:

  • 尽量只临时关闭,或仅关闭阻塞你当前工作的个别子选项,而不是整个 "strict": false
  • 在关键模块、核心域模型里保持严格。
  • 逐步还债:为公共 API、数据边界(网络、存储、DOM)补上类型。

渐进式启用的建议

  • 打开 "strict": true,如果报错太多,逐个关闭必要的子选项,再计划性回收:

    • 先解决 "noImplicitAny""strictNullChecks"(收益最大)。
    • 再处理 "strictPropertyInitialization""noImplicitThis" 等。
  • 配合 ESLint(typescript-eslint)规则,保持一致的代码风格与安全约束。

  • 在项目中引入额外的安全选项(即便不在 strict 内):

    • "noUncheckedIndexedAccess": true(索引访问返回 T | undefined
    • "exactOptionalPropertyTypes": true(可选属性更精确)
  • 对外部输入做运行时校验(zod、io-ts),让类型安全与数据校验形成闭环。

总结

  • 关闭 "strict" 会让 TypeScript 更宽松、上手更快,但潜在运行时错误更容易漏网,重构成本和风险上升。
  • 严格模式能在"写代码"而不是"跑起来"时暴露问题,长期能显著提升代码质量与信心。
  • 如果历史原因不得不开启宽松模式,也应规划渐进式回到严格,至少保证关键路径与公共接口的类型安全。
相关推荐
weixin_382395237 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__7 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.8 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~9 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华9 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子12 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅12 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni12 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学13 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端