共计 4909 个字符,预计需要花费 13 分钟才能阅读完成。
前言
文中内容都是参考 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