前言

文中内容都是参考https://www.typescriptlang.org/docs/handbook/2/typeof-types.html , 以及参考
TypeScript 之 Typeof Type Operator --- mqyqingfeng 内容。

typeof 类型操作符

先来看看JavaScript中typeof的用法:
具体可参考 MDN typeof

typeof 操作符返回一个字符串,示意未经计算的操作数的类型。
类型后果
Undefined"undefined"
Null"object"
Boolean"boolean"
Number"number"
BigInt(ECMAScript 2020 新增)"bigint"
String"string"
Symbol (ECMAScript 2015 新增)"symbol"
宿主对象(由 JS 环境提供)取决于具体实现
Function 对象"function"
其余任何对象"object"
// Undefinedtypeof undefined === 'undefined';   // truetypeof declaredButUndefinedVariable === 'undefined';  // truetypeof null === 'object'; // true 

TypeScript中的typeof常见用处是在类型上下文中获取变量或者属性的类型, 此外还能够配合ReturnType获取函数的返回值类型, 以及配合 keyof 应用。
如:

1. 获取变量类型

function fn (x: string | number) {  if (typeof x === 'string') {    x.toFixed(2);       // Property 'toFixed' does not exist on type 'string'.    return x.split('');    }    // ...}

2. 获取对象的类型

interface IPerson {  name: string;  age: number;  }let person: IPerson = {  name: 'xman',  age: 18  };type Person = typeof person;let p: Person = {  name: 'zxx',  age: 20  }

以上代码中通过typeof获取到person对象的类型,之后咱们就能够应用Person类型。
对于嵌套对象也是一样:

const userInfo = {  name: 'xman',  age: 18,  address: {    provice: '湖北',    city: '武汉'  }  }type UserInfo = typeof userInfo;

此时UserInfo类型如下:

type UserInfo = {  name: string;  age: number;  address: {    provice: string;    city: string;  };}  

对只读属性的数组:

let arr: readonly number[] = [1, 2, 3];type Type = typeof arr;// type Type = readonly number[]let arr1: Type = [2, 100];arr1.push(1);// type Type = readonly number[]

3. 获取函数的类型

function add (x: number, y: number): number {  return x + y;  }type Add = typeof add;

此时Add类型为

type Add = (x: number, y: number) => number

看下如果没有显式的形容函数返回类型,typeof会不会显示出返回类型:

function fn(x: string | number) {  if (typeof x === "string") {    return x.split("");  }  return x;}type Fn = typeof fn;

此时Fn类型为:

type T = (x: string | number) => number | string[]

能够看出, 返回类型都推断进去了。

4. 对 enum 应用 typeof

enum 是一种新的数据类型,但在具体运行的时候,它会被编译成对象

enum Direction {  Up = 1,  Down,  Left,  Right,}

编译成JS后代码:

"use strict";var Direction;(function (Direction) {  Direction[(Direction["Up"] = 1)] = "Up";  Direction[(Direction["Down"] = 2)] = "Down";  Direction[(Direction["Left"] = 3)] = "Left";  Direction[(Direction["Right"] = 4)] = "Right";})(Direction || (Direction = {}));

Direction值为:

{  1: "Up",  2: "Down",  3: "Left",  4: "Right",  Up: 1,  Down: 2,  Left: 3,  Right: 4,};

对Direction应用typeof

type Result = typeof Direction;let res: Result = {  Up: 2,  Down: 4,  Left: 6,  Right: 8,};

此时Result类型相似于:

{  Up: number,  Down: number,  Left: number,  Right: number,}

5. 对class 应用 typeof

class Person {  name: string;  age: number;  constructor(name: string, age: number) {    this.name = name;    this.age = age;  }}let PersonClass: typeof Person;// let PersonClass: new (name: string, age: number) => Personlet person = new PersonClass("xman", 18);

应用typeof Person,意思是取Person类的类型,而不是实例的类型。 或者更确切的说:获取Person标识符的类型,也就是构造函数的类型。 这个类型蕴含了类的所有动态成员和构造函数。 之后,咱们在PersonClass上应用new,创立PersonClass的实例。

6. 配合ReturnType获取函数的返回值类型

ReturnType定义:

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

infer在这里用于提取函数类型的返回值类型。ReturnType<T> 只是将 infer R 从参数地位挪动到返回值地位,因而此时 R 即是示意待推断的返回值类型。

应用:

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.

这是因为值(values)和类型(types)并不是一种货色。为了获取值 f 也就是函数 f 的类型,咱们就须要应用 typeof

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

7. 配合 keyof 应用

在 TypeScript 中,typeof 操作符能够用来获取一个变量或对象的类型。而 keyof 操作符能够用于获取某种类型的所有键,其返回类型是联结类型。
联合在一起应用:

const obj = {  name: "xman",  age: 18,};let k1: keyof typeof obj;// let k1: "name" | "age"const obj = {  1: 'one',  2: 'two',  3: 'three'} type k1 = keyof typeof obj;// typeof obj 的后果为 {//   1: string;//   2: string;//   3: string;// }// type k1 = 1 | 2 | 3enum Direction {  Up = 1,  Down,  Left,  Right,}type Result = keyof typeof Direction;// type Result = "Up" | "Down" | "Left" | "Right"

8. 对 const 断言字面量应用

let str1 = 'hello';// let str1: stringtype T1 = typeof str;// type T1 = stringlet str2 = 'hello' as const;// let str2 = 'hello' as const;type T2 = typeof str2;// type T2 = "hello"

数组字面量利用 const 断言后,它将变成 readonly 元组,通过 typeof 操作符获取元组中元素值的联结类型

let arr1 = [1, 2, 3];// let arr1: number[]type T1 = typeof arr1;// type T1 = number[]let arr2 = [1, 2, 3] as const;// let arr2: readonly [1, 2, 3]type T2 = typeof arr2;// type T2 = readonly [1, 2, 3]

对象字面量利用 const断言后, 对象字面量的属性,将应用 readonly 润饰

let obj1 = { name: "xman", age: 18 };// let obj1: {//   name: string;//   age: number;// };type T1 = typeof obj1;// type T1 = {//   name: string;//   age: number;// };let obj2 = { name: "xman", age: 18 } as const;// let obj2: {//   readonly name: "xman";//   readonly age: 18;// };type T2 = typeof obj2;// type T2 = {//   readonly name: "xman";//   readonly age: 18;// };

同样实用于蕴含援用类型的数组:

let arr1 = [  { name: "xman", age: 18 },  { name: "zxx", age: 22 },];// let arr1: {//   name: string;//   age: number;// }[];type T1 = typeof arr1;// type T1 = {//   name: string;//   age: number;// }[];let arr2 = [  { name: "xman", age: 18 },  { name: "zxx", age: 22 },] as const;// let arr2: readonly [//   {//     readonly name: "xman";//     readonly age: 18;//   },//   {//     readonly name: "zxx";//     readonly age: 22;//   }// ];type T2 = typeof arr2;// type T2 = readonly [//   {//     readonly name: "xman";//     readonly age: 18;//   },//   {//     readonly name: "zxx";//     readonly age: 22;//   }// ];type T3 = typeof arr2[number]['name'];// type T3 = "xman" | "zxx"

以上ts代码均在 https://www.typescriptlang.or... 上运行过,版本为4.7.2。
最初, 如有谬误,欢送各位大佬指导!感激!

参考资料

https://www.typescriptlang.org/docs/handbook/2/typeof-types.html
https://github.com/mqyqingfeng/Blog/issues/224