为什么 any 可以分配给 TypeScript 中的每种类型

Why can any be assigned to every type in TypeScript

这是一个关于 TypeScript 类型结构的哲学问题。

让我们看看下面的简短片段 (available as a playground here)。

function f(): string {
    if (Math.random() > 0.5) {
        return 'a real string';
    }
    var x: any = null;
    // Why does this type check?
    return x;
}

const myString = f();
// myString has type string
// not string | any, not string | undefined, not string | null
// so I expect it to really be a string
console.log(myString.length);
// -> TypeError: null is not an object (evaluating myString.length)

简而言之,我的问题是为什么这个例子编译时启用了所有可能的严格标志?

any 上的文档指出 any 用于“描述我们不知道的变量类型”。因此,所有类型都可以分配给 any是有道理的,但是,为什么any可以分配给所有其他类型?

就其本质而言,类型为 any 的对象具有未知属性,那么为什么可以在没有警告的情况下将它们编组为其他类型(如 string)?当我们知道编译器没有强制执行它们的内容时,这不会破坏用类型显式标记事物的目的吗?

例如,假设我想定义一个明确地 returns 一个 string 的函数(不是 null,不是 undefined,不是 number,但恰好 string)。有没有办法让 TypeScript 编译器强制每个 returns 来自该函数 returns 的代码路径都是一个字符串?我的先入之见是上面的例子 应该 这样做,我们应该看到像 any is not assignable to type string 这样的错误,但我们没有。

The documentation on any states that any is used to "describe the type of variables that we do not know"

从 TypeScript 3.0 开始,您应该使用 unknown 来描述此类类型。

any 是过去的神器,你不应该使用它,除非你不能使用 unknown。有一些(神秘的)。

解决方案

function f(): string {
    if (Math.random() > 0.5) {
        return 'a real string';
    }
    var x: unknown = null;
    return x; // Compile-time error: "Type 'unknown' is not assignable to type 'string'.(2322)"
}