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 any
和 as unknown
也是我们手动给一个类型转成 any
和 known
。any
类型放弃了所有的类型安全,而 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
经常在一些第三方库中看到,但是在编码时,理想情况下,尽量不要使用它。哈哈哈~😄