来了解一下TS中的类型断言吧~

108 阅读3分钟

类型断言是什么

TypeScript中的类型断言允许开发者手动指定一个值的类型。这在某些情况下非常有用,比如当你需要绕过类型系统的某些限制,或者当你确信某个值的类型比类型系统推断的类型更具体时。

很多时候,它比你到处写any更加有效,直观的多。

就比如下面这个例子。

type T = 'a'|'b'|'c';
let foo = 'a';

let bar:T = foo; // 报错

在这个例子中,TS推断变量foo的类型是string,但是变量bar的类型是'a'|'b'|'c',前者是后者的父类型,父类型不能赋值给子类型。所以就最后一行报错了。

为了解决这一个问题,TS提供了类型断言这样一种手段,允许在代码中“断言”某个值的类型,告诉编译器此处的值是什么类型。

TS一旦发现存在类型断言,就不再对该值进行类型推断,而是直接采用断言给出的类型。

所以上面的例子可以改成这样。

type T = 'a'|'b'|'c';

let foo = 'a';
let bar:T = foo as T; // 正确

最后一行的foo as T表示告诉编译器,变量foo的类型断言为T ,所以这一行不再需要类型推断了,编译器直接把foo的类型当作T ,就不会报错了。

类型断言的使用条件

类型断言并是把某个值断言为任意类型。 下面的例子中,变量n是数值,无法把它断言成字符串,TS就会报错。

const n = 1;
const m:string = n as string; // 报错

类型断言的使用前提是,值的实际类型与断言的类型必须满足一个条件。 valueType的子类型,或者Typevalue的子类型。

n as string
// 这里n是number类型,和string类型不构成子类型条件,所以不满足类型断言的前提

但是,如果真的要断言成一个完全无关的类型,也是可以做到的。

那就是连续进行两次类型断言,先断言成unknown类型或any类型,然后再断言为目标类型。

因为any类型和unknown类型是所有其他类型的父类型,所以可以作为两种完全无关的类型的中介。

value as unknown as Type

as const 断言

TS中,如果没有声明变量类型:

  1. let 命令声明的变量,会被类型推断为TS内置的基本类型之一;
  2. const 命令声明的变量,则被推断为值类型常量。
// 类型推断为基本类型 string
let s1 = 'JavaScript';

// 类型推断为字符串 “JavaScript”
const s2 = 'JavaScript';

除了改成const 命令之外,TS提供了一种特殊的类型断言as const,用于告诉编译器,推断类型时,可以将这个值推断为常量。

image.png

易错点

const tuple = ["tesla", "model 3", "model X", "model Y"] as const;
type TupleToObject<T as string[]> = {
  [P in T[number]]: P;
};
type result = TupleToObject<typeof tuple>;

image.png

直接报语法错误

原因

为什么 as 在这里不适用将泛型T的类型指定为string[]类型:

  1. 类型断言as 用于在值的层面上进行类型断言,而不是在类型层面上。泛型参数的约束是在类型层面上定义的。
  2. 泛型约束语法:TypeScript 要求泛型参数的约束使用 extends 语法,这是泛型参数约束的标准语法。

用extend去修饰就好了~