关于ts的as unknown as T

88 阅读2分钟

TS只有编译器,没有虚拟机。

TypeScript 的主要目的是在 JavaScript 的基础上提供静态类型检查和更丰富的语言特性,以提高开发效率和代码质量。它通过编译器将 TypeScript 代码转换为可以在 JavaScript 虚拟机(如浏览器中的 V8 引擎或 Node.js 中的 V8 引擎)上运行的 JavaScript 代码。

所以无论在 TypeScript 编写了哪些代码,是交给编译器用的,运行时 V8 的输入是 JavaScript。

TypeScript 怎样理解 as unknown as Tas T

它不允许在不兼容的类型之间进行赋值或操作,除非明确告知编译器这样做是安全的。as T 是一种类型断言,但它受到一定限制。编译器只允许在两种类型之间进行“合理”的转换。例如:

  • (someValue as string).toUpperCase():如果 someValue 的实际类型是 string 或其子类型,这是允许的。
  • (someNumber as number).toFixed(2):这也是允许的,因为 someNumber 的实际类型很可能是 number

然而,如果尝试在完全不相关的类型之间进行转换,编译器会报错。例如:

interface Person {
    name: string;
    age: number;
}

const someObject = { x: 10, y: 20 }; 
const person = someObject as Person; // 编译器报错

这是因为 someObjectPerson 之间没有兼容性。

as unknown as T 的作用

as unknown as T 是一种更“强大”的类型断言。它允许绕过编译器的类型检查,将任何值转换为任何类型。这是通过两步实现的:

  1. as unknown:将值转换为 unknown 类型。unknown 是 TypeScript 中最宽松的类型,可以表示任何值。
  2. as T:将 unknown 值转换为目标类型 T

这种双重断言有效地告诉编译器:“我知道我在做什么,请相信我”。

何时必须使用 as unknown as T

当需要在完全不相关的类型之间进行转换时,必须使用 as unknown as T。以下是一些例子:

1、从任意对象创建类实例

class MyClass {
    constructor(public value: number) {}
}

const someObject = { a: 'hello', b: true };
const myInstance = new MyClass((someObject as unknown as { value: number }).value);

2、处理来自外部库的数据

declare function getExternalData(): any;

interface MyData {
    id: number;
    name: string;
}

const data = getExternalData() as unknown as MyData[];

3、在复杂的类型体操中

type MyComplexType = ...; // 某种复杂的类型

function processValue(value: unknown): MyComplexType {
    // ... 一些复杂的逻辑
    return (value as unknown as MyComplexType);
}

as unknown as T 是一种强大的类型断言,允许在 TypeScript 中绕过类型检查。当需要在完全不相关的类型之间进行转换时,它很有用。然而,它应该谨慎使用,因为滥用它可能会导致运行时错误

处理来自外部库的数据而言,如果使用了getExternalData() as unknown as MyData[],接下来getExternalData()的值可以使用MyData[]类型中存在的定义,但是在运行时是否有错误,TypeScript 编译器不能保证,是交给程序员去保证的。