Typescript在给我们提供严格的类型安全的同时,也可能给我们带来麻烦,有时候实在想转成其他类型来规避类型错误提示。最常见的是 as any 语法,然而我们都知道,使用了 as any 就失去了类型安全了,还不如不用。这时候 as unknown as 可以让我们做类型转换的同时还能保持类型安全。

unknown类型是什么?

简单来说,unknown 表示一个类型,意味着 “我不知道这是什么,它什么都不能做”。它类似于 any 类型,意味着 “我不知道这是什么,它能做任何事”。

as类型断言

在ts里面,类型断言(Type Assertion)是一种让开发者明确指定一个值的类型的手段。在我们知道一个值的类似,当时编译器推断不出来的时候,就可以告诉编译器这个是什么。

比如在操作dom元素的时候,我们经常需要手动指定类型。

const element = document.getElementById('myElement');

if (element) {
  const myElement: HTMLInputElement = element as HTMLInputElement;
  console.log(myElement.value); // 假设 "myElement" 是一个 input 元素
}

所以上述的 as anyas unknown 也是我们手动给一个类型转成 anyknownany 类型放弃了所有的类型安全,而 unknown 类型则保留了一定程度的类型安全。unknown 类型可以被断言到任何类型

类型S是类型T的子类型

类型S是类型T的子类型的意思是S拥有T的所有属性和方法,并且有自己的额外属性和方法。如果类型S是类型T的子类型,那么类型S的对象可以被赋值给类型T的变量,这是因为类型S的对象包含了类型T所要求的所有信息。这符合里氏替换原则,即子类型能够替换掉它们的基类型。

interface Site {
  name: string;
}

interface WebSite extends Site {
  url: string;
}

let website: WebSite = { name: 'kelen.cc', url: 'https://www.kelen.cc' };
let site: Site = website; // 这是一个安全的类型赋值

let siteAsWebSite: WebSite = site as WebSite; // 类型断言,也是安全的

上述的 WebSite 就是 Site 的子类型,所以两者可以互相转换而不会报错。

as unknown as

as unknown as 双重断言,我们知道,unknown 可以断言为任意类型(通常不会那样做,但是实际是可以转成 unknown 的),任意类型可以断言为 unknown,所以 unknown 就可以作为中间桥梁让所有类型进行任意转换。与 as any as 功能是一摸一样的。

let value: number = 123; // value 的类型现在是 number
let stringValue: string = value as unknown as string; // 此时 stringValue 的类型是 string
console.log(stringValue.toUpperCase()); // 编译器现在允许调用 string 方法

as unknown as 经常在一些第三方库中看到,但是在编码时,理想情况下,尽量不要使用它。哈哈哈~😄