• 说明:目前网上没有 TypeScript 最新官方文档的中文翻译,所以有了这么一个翻译计划。因为我也是 TypeScript 的初学者,所以无法保证翻译百分之百准确,若有错误,欢迎评论区指出;
  • 翻译内容:暂定翻译内容为 TypeScript Handbook,后续有空会补充翻译文档的其它部分;
  • 项目地址TypeScript-Doc-Zh,如果对你有帮助,可以点一个 star ~

本章节官方文档地址:Keyof Type OperatorTypeof Type Operator

Keyof 类型操作符

keyof 类型操作符

keyof 类型操作符接受一个对象类型作为参数,并基于它的键产生一个由字符串字面量或者数值字面量组成的联合类型。下面的类型 P 等同于类型 "x" | "y"

type Point = { x: number; y: number };
type P = keyof Point;
	^
   // type P = keyof Point     

如果 keyof 操作的类型有 string 或者 number 类型的索引签名,那么 keyof 会返回该索引签名的类型:

type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish;
     ^
   // type A = number
 
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
     ^
   // type M = string | number

注意,在这个例子中,M 表示的类型是 string | number —— 这是因为 JavaScript 对象的键总是会被强制转化为一个字符串,因此 obj[0] 等同于 obj["0"]

keyof 类型和映射类型结合的时候会发挥很大的作用,后续的章节我们也会进行介绍。

Typeof 类型操作符

typeof 类型操作符

JavaScript 中本身就有一个可用于表达式上下文的 typeof 操作符:

// 打印 "string"
console.log(typeof "Hello world");

TypeScript 则添加了一个可用于类型上下文的 typeof 操作符,让你可以引用某个变量或者属性的类型:

let s = "hello";
let n: typeof s;
	^
    // let n: string

像上面这样用于基本类型,作用并不是很大,但如果把 typeof 和其它类型操作符结合使用,就可以方便地表示多种模式了。举个例子,我们先来看一下预定义类型 ReturnType<T>。它可以接受一个函数类型并将它的返回值类型返回出去:

type Predicate = (x: unknown) => boolean;
type K = ReturnType<Predicate>;
	 ^
    // type K = boolean     

如果直接把函数名作为参数传递给 ReturnType,那么我们会看到一个指示性错误:

function f() {
  return { x: 10, y: 3 };
}
type P = ReturnType<f>;
				  ^	
// 'f' refers to a value, but is being used as a type here. Did you mean 'typeof f'?

记住,值和类型是不一样的,这里应该传入类型而不是值,因此我们可以改用 typeof 去引用值 f 的类型:

function f(){
    return {
        x: 10,
        y: 3
    };
}
type P = ReturnType<typeof f>;
	 ^
   /* type P = {
    	x: number;
    	y: number;
	 }            */   

限制

TypeScript 有意限制 typeof 可以操作的表达式类型。具体地说,tyepof 只能作用于标识符(比如变量名)或者它们的属性。这可以避免让开发者编写他们认为可以执行的但实际上不能执行的代码:

// 这里应该改用 = ReturnType<typeof msgbox>
let shouldContinue: typeof msgbox("Are you sure you want to continue?");
							^			
// ',' expected.