qrcode

关注全栈修仙之路,一起学习进阶!

TypeScript typeof 操作符

Welcome to the Mastering TypeScript series. This series will introduce the core knowledge and techniques of TypeScript in the form of animations. Let’s learn together! Previous articles are as follows:

阅读须知:本文示例的运行环境是 TypeScript 官网的 Playground,对应的编译器版本是 v3.8.3

一、typeof 简介

在 TypeScript 中,typeof 操作符可以用来获取一个变量或对象的类型。

1
2
3
4
5
6
7
interface Person {
name: string;
age: number;
}

const sem: Person = { name: "semlinker", age: 30 };
type Sem = typeof sem; // type Sem = Person

在上面代码中,我们通过 typeof 操作符获取 sem 变量的类型并赋值给 Sem 类型变量,之后我们就可以使用 Sem 类型:

1
const lolo: Sem  = { name: "lolo", age: 5 }

你也可以对嵌套对象执行相同的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const kakuqo = {
name: "kakuqo",
age: 30,
address: {
province: '福建',
city: '厦门'
}
}

type Kakuqo = typeof kakuqo;
/*
type Kakuqo = {
name: string;
age: number;
address: {
province: string;
city: string;
};
}
*/

此外,typeof 操作符除了可以获取对象的结构类型之外,它也可以用来获取函数对象的类型,比如:

1
2
3
4
5
function toArray(x: number): Array<number> {
return [x];
}

type Func = typeof toArray; // -> (x: number) => number[]

二、const 断言

TypeScript 3.4 引入了一种新的字面量构造方式,也称为 const 断言。当我们使用 const 断言构造新的字面量表达式时,我们可以向编程语言发出以下信号:

  • 表达式中的任何字面量类型都不应该被扩展;
  • 对象字面量的属性,将使用 readonly 修饰;
  • 数组字面量将变成 readonly 元组。

下面我们来举一个 const 断言的例子:

1
2
3
4
5
6
7
8
let x = "hello" as const;
type X = typeof x; // type X = "hello"

let y = [10, 20] as const;
type Y = typeof y; // type Y = readonly [10, 20]

let z = { text: "hello" } as const;
type Z = typeof z; // let z: { readonly text: "hello"; }

数组字面量应用 const 断言后,它将变成 readonly 元组,之后我们还可以通过 typeof 操作符获取元组中元素值的联合类型,具体如下:

1
type Data = typeof y[number]; // type Data = 10 | 20

这同样适用于包含引用类型的数组,比如包含普通的对象的数组。这里我们也来举一个具体的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
const locales = [
{
locale: "zh-CN",
language: "中文"
},
{
locale: "en",
language: "English"
}
] as const;

// type Locale = "zh-CN" | "en"
type Locale = typeof locales[number]["locale"];

另外在使用 const 断言的时候,我们还需要注意以下两个注意事项:

  1. const 断言只适用于简单的字面量表达式
1
2
3
4
5
6
// A 'const' assertions can only be applied to references to enum members, 
// or string, number, boolean, array, or object literals.
let a = (Math.random() < 0.5 ? 0 : 1) as const; // error

let b = Math.random() < 0.5 ? 0 as const :
1 as const;
  1. const 上下文不会立即将表达式转换为完全不可变
1
2
3
4
5
6
7
8
9
10
11
let arr = [1, 2, 3, 4];

let foo = {
name: "foo",
contents: arr,
} as const;

foo.name = "bar"; // error!
foo.contents = []; // error!

foo.contents.push(5); // ...works!

三、typeof 和 keyof 操作符

在 TypeScript 中,typeof 操作符可以用来获取一个变量或对象的类型。而 keyof 操作符可以用于获取某种类型的所有键,其返回类型是联合类型。了解完 typeofkeyof 操作符的作用,我们来举个例子,介绍一下它们如何结合在一起使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const COLORS = {
red: 'red',
blue: 'blue'
}

// 首先通过typeof操作符获取Colors变量的类型,然后通过keyof操作符获取该类型的所有键,
// 即字符串字面量联合类型 'red' | 'blue'
type Colors = keyof typeof COLORS
let color: Colors;
color = 'red' // Ok
color = 'blue' // Ok

// Type '"yellow"' is not assignable to type '"red" | "blue"'.
color = 'yellow' // Error

四、参考资源


欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。

qrcode