类型检查
allowUnreachableCode
- 发布版本: 1.8
当:
undefined(默认)向编辑器提供建议作为警告true忽略无法访问的代码false引发有关无法访问代码的编译器错误
这些警告仅涉及由于使用 JavaScript 语法而证明无法访问的代码,例如:
function fn(n: number) {
if (n > 5) {
return true;
} else {
return false;
}
return true;
}当 "allowUnreachableCode": false 时:
function fn(n: number) {
if (n > 5) {
return true;
} else {
return false;
}
return true;Unreachable code detected.}Try这不影响基于类型分析看似无法访问的代码的错误。
allowUnusedLabels
- 发布版本: 1.8
当:
undefined(默认)向编辑器提供建议作为警告true忽略未使用的标签false引发有关未使用标签的编译器错误
标签在 JavaScript 中非常罕见,通常表示试图编写对象字面量:
function verifyAge(age: number) {
// 忘记 'return' 语句
if (age > 18) {
verified: true;Unused label. }
}TryalwaysStrict
确保你的文件以 ECMAScript 严格模式解析,并为每个源文件输出 "use strict"。
ECMAScript 严格模式 在 ES5 中引入,为 JavaScript 引擎的运行时提供了行为调整以提高性能,并使一组错误抛出而不是静默忽略。
exactOptionalPropertyTypes 推荐
- 发布版本: 4.4
启用 exactOptionalPropertyTypes 后,TypeScript 对 type 或 interface 中带有 ? 前缀的属性应用更严格的规则。
例如,此接口声明有一个属性可以是两个字符串之一:'dark' 或 'light',或者不应在对象中。
interface UserDefaults {
// 值的缺失表示 'system'
colorThemeOverride?: "dark" | "light";
}未启用此标志时,colorThemeOverride 可以设置为三个值:"dark"、"light" 和 undefined。
将值设置为 undefined 将使大多数 JavaScript 运行时对存在性的检查失败,这实际上是假值。然而,这并不完全准确;colorThemeOverride: undefined 与未定义 colorThemeOverride 是不同的。例如,"colorThemeOverride" in settings 在 undefined 作为键与未定义时的行为不同。
exactOptionalPropertyTypes 使 TypeScript 真正强制执行作为可选属性提供的定义:
const settings = getUserSettings();
settings.colorThemeOverride = "dark";
settings.colorThemeOverride = "light";
// 但不允许:
settings.colorThemeOverride = undefined;Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.TrynoFallthroughCasesInSwitch
- 发布版本: 1.8
报告 switch 语句中的贯穿 case 错误。 确保 switch 语句中的任何非空 case 都包含 break、return 或 throw。 这意味着你不会意外发布 case 贯穿 bug。
const a: number = 6;
switch (a) {
case 0:Fallthrough case in switch. console.log("even");
case 1:
console.log("odd");
break;
}TrynoImplicitAny 推荐
在某些没有类型注解的情况下,当 TypeScript 无法推断类型时,它将回退到变量的 any 类型。
这可能导致遗漏一些错误,例如:
启用 noImplicitAny 后,每当 TypeScript 会推断为 any 时,它将发出错误:
noImplicitOverride
- 发布版本: 4.3
当使用继承的类时,子类可能会在基类中重命名的函数被重载时与它们“不同步”。
例如,假设你在建模一个音乐专辑同步系统:
class Album {
download() {
// 默认行为
}
}
class SharedAlbum extends Album {
download() {
// 覆盖以从多个来源获取信息
}
}Try然后当你添加对机器学习生成的播放列表的支持时,你将 Album 类重构为有一个 'setup' 函数而不是:
class Album {
setup() {
// 默认行为
}
}
class MLAlbum extends Album {
setup() {
// 覆盖以从算法获取信息
}
}
class SharedAlbum extends Album {
download() {
// 覆盖以从多个来源获取信息
}
}Try在这种情况下,TypeScript 没有提供警告,SharedAlbum 上的 download 期望覆盖基类中的一个函数。
使用 noImplicitOverride,你可以通过确保覆盖的函数包含关键字 override 来确保子类永远不会不同步。
以下示例启用了 noImplicitOverride,你可以看到当 override 缺失时收到的错误:
class Album {
setup() {}
}
class MLAlbum extends Album {
override setup() {}
}
class SharedAlbum extends Album {
setup() {}This member must have an 'override' modifier because it overrides a member in the base class 'Album'.}TrynoImplicitReturns
- 发布版本: 1.8
启用后,TypeScript 将检查函数中的所有代码路径以确保它们返回值。
function lookupHeadphonesManufacturer(color: "blue" | "black"): string {Function lacks ending return statement and return type does not include 'undefined'. if (color === "blue") {
return "beats";
} else {
"bose";
}
}TrynoImplicitThis 推荐
对带有隐含 any 类型的 'this' 表达式引发错误。
例如,下面的类返回一个试图访问 this.width 和 this.height 的函数——但 getAreaFunction 内部函数中的 this 上下文不是 Rectangle 的实例。
class Rectangle {
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
getAreaFunction() {
return function () {
return this.width * this.height;'this' implicitly has type 'any' because it does not have a type annotation.'this' implicitly has type 'any' because it does not have a type annotation. };
}
}TrynoPropertyAccessFromIndexSignature
- 发布版本: 4.2
此设置确保通过“点”(obj.key)语法和“索引”(obj["key"])语法访问字段的方式与属性在类型中声明的方式一致。
如果没有此标志,TypeScript 将允许你使用点语法访问未定义的字段:
interface GameSettings {
// 预先知道的属性
speed: "fast" | "medium" | "slow";
quality: "high" | "low";
// 假设接口未知的任何内容
// 都是字符串。
[key: string]: string;
}
const settings = getSettings();
settings.speed;
settings.quality;
// 未知键访问器在此对象上是允许的,
// 并且是 `string`
settings.username;
Try打开标志将引发错误,因为未知字段使用了点语法而不是索引语法。
const settings = getSettings();
settings.speed;
settings.quality;
// 这应该是 settings["username"];
settings.username;Property 'username' comes from an index signature, so it must be accessed with ['username'].Try此标志的目标是在你的调用语法中表明你对这个属性存在的确定性程度。
noUncheckedIndexedAccess
- 发布版本: 4.1
TypeScript 有一种通过索引签名描述对象具有未知键但已知值的方式。
interface EnvironmentVars {
NAME: string;
OS: string;
// 未知属性由此索引签名覆盖。
[propName: string]: string;
}
declare const env: EnvironmentVars;
// 声明为存在
const sysName = env.NAME;
const os = env.OS;
// 未声明,但由于索引签名,它被视为字符串
const nodeEnv = env.NODE_ENV;
Try启用 noUncheckedIndexedAccess 将为类型中任何未声明的字段添加 undefined。
declare const env: EnvironmentVars;
// 声明为存在
const sysName = env.NAME;
const os = env.OS;
// 未声明,但由于索引签名,它被视为字符串
const nodeEnv = env.NODE_ENV;
TrynoUnusedLocals
- 发布版本: 2.0
报告未使用的局部变量的错误。
const createKeyboard = (modelID: number) => {
const defaultModelID = 23;'defaultModelID' is declared but its value is never read. return { type: "keyboard", modelID };
};TrynoUnusedParameters
- 发布版本: 2.0
报告函数中未使用参数的错误。
const createDefaultKeyboard = (modelID: number) => {'modelID' is declared but its value is never read. const defaultModelID = 23;
return { type: "keyboard", modelID: defaultModelID };
};Try参数声明以 _ 开头的名称不受未使用参数检查的影响。例如:
strict 推荐
默认值:
true发布版本: 2.3
相关: alwaysStrict,strictNullChecks,strictBindCallApply,strictBuiltinIteratorReturn,strictFunctionTypes,strictPropertyInitialization,noImplicitAny,noImplicitThis,useUnknownInCatchVariables
strict 标志启用广泛的类型检查行为,从而产生更强的程序正确性保证。 启用此标志相当于启用下面列出的所有严格模式系列选项。 然后你可以根据需要关闭各个严格模式系列检查。
未来版本的 TypeScript 可能会在此标志下引入额外的更严格检查,因此升级 TypeScript 可能会导致你的程序中出现新的类型错误。 在适当和可能的情况下,将添加相应的标志来禁用该行为。
strictBindCallApply 推荐
设置后,TypeScript 将检查内置函数方法 call、bind 和 apply 是否使用底层函数的正确参数调用:
// 启用 strictBindCallApply 时
function fn(x: string) {
return parseInt(x);
}
const n1 = fn.call(undefined, "10");
const n2 = fn.call(undefined, false);Argument of type 'boolean' is not assignable to parameter of type 'string'.Try否则,这些函数接受任何参数并将返回 any:
// 禁用 strictBindCallApply 时
function fn(x: string) {
return parseInt(x);
}
// 注意:没有错误;返回类型是 'any'
const n = fn.call(undefined, false);TrystrictBuiltinIteratorReturn 推荐
内置迭代器使用 undefined 而不是 any 作为 TReturn 类型实例化。
strictFunctionTypes 推荐
启用后,此标志会使函数参数被更正确地检查。
这是一个 strictFunctionTypes 关闭的基本示例:
function fn(x: string) {
console.log("Hello, " + x.toLowerCase());
}
type StringOrNumberFunc = (ns: string | number) => void;
// 不安全的赋值
let func: StringOrNumberFunc = fn;
// 不安全的调用 - 将崩溃
func(10);Try启用 strictFunctionTypes 后,错误被正确检测到:
function fn(x: string) {
console.log("Hello, " + x.toLowerCase());
}
type StringOrNumberFunc = (ns: string | number) => void;
// 防止了不安全的赋值
let func: StringOrNumberFunc = fn;Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'.
Types of parameters 'x' and 'ns' are incompatible.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.Try在开发此功能期间,我们发现大量本质上不安全的类层次结构,包括 DOM 中的一些。 因此,此设置仅适用于用函数语法编写的函数,而不适用于用方法语法编写的函数:
type Methodish = {
func(x: string | number): void;
};
function fn(x: string) {
console.log("Hello, " + x.toLowerCase());
}
// 最终是不安全的赋值,但未检测到
const m: Methodish = {
func: fn,
};
m.func(10);TrystrictNullChecks 推荐
当 strictNullChecks 为 false 时,语言实际上忽略了 null 和 undefined。 这可能导致运行时出现意外错误。
当 strictNullChecks 为 true 时,null 和 undefined 有其自己的不同类型,如果你试图在需要具体值的地方使用它们,你将收到类型错误。
例如,使用此 TypeScript 代码,users.find 不能保证它实际上会找到一个用户,但你可以像它会找到一样编写代码:
declare const loggedInUsername: string;
const users = [
{ name: "Oby", age: 12 },
{ name: "Heera", age: 32 },
];
const loggedInUser = users.find((u) => u.name === loggedInUsername);
console.log(loggedInUser.age);Try将 strictNullChecks 设置为 true 将引发错误,即你在尝试使用 loggedInUser 之前没有保证其存在。
declare const loggedInUsername: string;
const users = [
{ name: "Oby", age: 12 },
{ name: "Heera", age: 32 },
];
const loggedInUser = users.find((u) => u.name === loggedInUsername);
console.log(loggedInUser.age);'loggedInUser' is possibly 'undefined'.Try第二个示例失败是因为数组的 find 函数看起来有点像这个简化:
// 当 strictNullChecks: true
type Array = {
find(predicate: (value: any, index: number) => boolean): S | undefined;
};
// 当 strictNullChecks: false 时,undefined 从类型系统中移除,
// 允许你编写假设总是找到结果的代码
type Array = {
find(predicate: (value: any, index: number) => boolean): S;
};strictPropertyInitialization 推荐
设置为 true 时,如果类属性已声明但未在构造函数中设置,TypeScript 将引发错误。
class UserAccount {
name: string;
accountType = "user";
email: string;Property 'email' has no initializer and is not definitely assigned in the constructor. address: string | undefined;
constructor(name: string) {
this.name = name;
// 注意没有设置 this.email
}
}Try在上面的例子中:
this.name被明确设置。this.accountType被默认设置。this.email未设置并引发错误。this.address被声明为可能为undefined,这意味着它不必被设置。
useUnknownInCatchVariables 推荐
在 TypeScript 4.0 中,添加了支持以允许将 catch 子句中的变量类型从 any 更改为 unknown。允许如下代码:
try {
// ...
} catch (err: unknown) {
// 我们必须验证 err 是一个
// 错误,然后才能将其作为错误使用。
if (err instanceof Error) {
console.log(err.message);
}
}Try此模式确保错误处理代码更全面,因为你无法提前保证抛出的对象是 Error 子类。启用 useUnknownInCatchVariables 标志后,你不需要额外的语法(: unknown)或 linter 规则来尝试强制执行此行为。