Typescript学习: unknown 与 any

推荐:使用 unknown 类型代替 any 类型
更新于: 2023-05-12 10:35:46

共同点

  • 都是 TypeScript 中的顶级类型,可以接受任何类型的值。

看下 any 与 unknown 不同的地方

  • unknown 实例
  • any 实例
  • 实际应用
let value: unknown;

value.foo.bar;  // Error
value.trim();   // Error
value();        // Error
new value();    // Error
value[0][1];    // Error
const doSomething = (val: any) => {
  val(); // no error
  val.foo.bar; // no error
}
function stringifyForLogging(value: unknown): string {
  // 断言之后,则可以使用 value
  if (typeof value === "function") {
    // Within this branch, `value` has type `Function`,
    // so we can access the function's `name` property
    const functionName = value.name || "(anonymous)";
    return `[function ${functionName}]`;
  }

  if (value instanceof Date) {
    // Within this branch, `value` has type `Date`,
    // so we can call the `toISOString` method
    return value.toISOString();
  }

  return String(value);
}

区别

  • 类型安全性:unknown是类型安全的,而any是不安全的。当使用unknown类型时,需要进行类型检查或类型断言才能将其分配给具体的类型。而any类型可以直接被分配给任何类型,不会触发类型检查。
  • 类型推断和操作:unknown会强制进行类型检查和类型推断。当使用unknown类型时,需要明确指定或进行类型断言才能进行操作或访问属性。而any类型不会触发类型检查,可以直接进行任何操作。
  • 类型约束:使用unknown可以保留更多的类型信息,而any是一种完全放开类型约束的类型。使用unknown可以在稍后的代码中对具体类型进行更精确的推断和操作。
let value: unknown;

// 1. 类型安全性
value = 123; // 可以分配任何类型的值
// value.foo; // 错误:无法访问未知类型的属性
// value(); // 错误:未知类型不能被调用

let anyValue: any;
anyValue = 123; // 可以分配任何类型的值
anyValue.foo; // 没有编译时错误,可以访问任意属性
anyValue(); // 没有编译时错误,可以调用任意值

// 2. 类型推断和操作
let value1: unknown;
let value2: any;

let inferred1 = value1; // unknown,无法推断具体类型
let inferred2 = value2; // any,无需推断,直接是 any 类型

let processed1 = value1 + 10; // 错误:无法对未知类型进行操作
let processed2 = value2 + 10; // 不会报错,可以对 any 进行操作

// 3. 类型约束
function processValue1(input: unknown) {
  // input + 10; // 错误:无法对未知类型进行操作
  if (typeof input === 'number') {
    input + 10; // 可以在类型检查后对其进行操作
  }
}

function processValue2(input: any) {
  input + 10; // 不会报错,可以直接进行操作
}

processValue1(123);
processValue2(123);

是否所有地方推荐用 unknown 代替 any?

特点: 类型安全的代码具备定义良好的数据类型

参考: https://baike.baidu.com/item/类型安全/7308285?fr=aladdin

不是所有情况下都建议使用unknown代替any。选择使用unknown还是any取决于具体的使用场景和需求。

下面是一些情况下建议使用unknown的场景:

更强的类型安全性:如果你想要在编译时更严格地检查类型,并明确要求进行类型检查或类型断言,那么使用unknown是一个好选择。它可以帮助捕获潜在的类型错误,并强制进行类型检查,提高代码的可靠性和健壮性。

需要精确的类型推断和操作:如果你需要在稍后的代码中对具体类型进行精确的推断和操作,使用unknown可以保留更多的类型信息,以便进行类型推断和类型安全的操作。

提供更具意义的类型约束:如果你想要明确表示某个值的类型是未知的,而不是任意的,使用unknown可以更准确地传达这种意图。

但是,也有一些情况下使用any更合适:

动态类型的情况:如果你处理的是动态类型的值,而且对类型的具体约束不太重要,可以使用any来简化代码。例如,在处理来自第三方库或外部数据源的值时,可能无法确定其具体类型,此时使用any可以灵活地处理这些值。

快速原型开发:如果你正在进行快速原型开发,临时代码或实验性代码,而不太关注类型的安全性,那么使用any可以减少类型相关的开发成本。

总而言之,使用unknown还是any取决于你对类型安全性、类型推断和操作、类型约束的要求。对于需要更严格的类型安全和约束的情况,unknown是更好的选择;而对于灵活性要求较高、动态类型或快速原型开发的情况,any可能更适合。

参考