关于typescript:TypeScript基础之typeof-类型操作符

前言

文中内容都是参考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”
// Undefined
typeof undefined === 'undefined';   // true
typeof declaredButUndefinedVariable === 'undefined';  // true

typeof 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) => Person

let 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 | 3

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

type Result = keyof typeof Direction;
// type Result = "Up" | "Down" | "Left" | "Right"

8. 对 const 断言字面量应用

let str1 = 'hello';
// let str1: string

type T1 = typeof str;
// type T1 = string

let 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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理