TypeScript typeof操作符
typeof
类型操作符
JavaScript本身就有typeof操作符,你可以在表达式上下文中使用:
console.log(typeof 'hello'); // print 'string'
而TypeScript添加的typeof方法可以在类型上下文中使用,用于获取一个变量或者属性的类型。
let s = 'hello';
let n: typeof s; // let n: string
如果仅仅用来判断基本的类型,那自然是没什么太大用,和其他的类型操作符搭配使用才能发挥它的作用。
举个例子:比如搭配TypeScript内置的ReturnType<T>
。传入一个函数类型,ReturnType<T>
会返回该函数返回值的类型。
type Fn = (x: unknown) => boolean;
type K = ReturnType<Fn>; //type K = boolean
如果我们对一个函数名使用ReturnType<T>
,会收到这样一条报错:
function fn(x: unknown):boolean {
return true;
}
type K = ReturnType<fn>; // 报错:“fn”表示值,但在此处用作类型。是否指“类型 fn”?
这是因为values
(值)和types
(类型)并不是一种东西,为了获取fn
的类型,我们可以用到typeof
:
function fn(x: unknown):boolean {
return true;
}
type K = ReturnType<typeof fn>; // type K = boolean
限制
TypeScript有意的限制了可以使用typeof
的表达式的种类。
在TypeScript中,只有对标识符(比如变量名)或者他们的属性使用typeof
才是合法的。这可能会导致一些令人迷惑的问题:
function msgBox(str: string): string {
return str
}
let fn: typeof msgBox('hello'); // ',' expected.
我们本想获取函数返回值的类型,但其实上面的写法是不能正常执行的,原因就是因为typeof
只能对属性或者标识符使用,而正确的写法应该是:
function msgBox(str: string): string {
return str
}
let fn: ReturnType<typeof msgBox>; // let fn: string
对对象使用typeof
我们可以对一个对象使用typeof
:
let p = {
name: 'zs',
age: 18
}
type res = typeof p;
// type res = {
// name: string;
// age: number;
// }
对函数使用typeof
我们也可以对一个函数使用typeof
:
function fn<T>(x: T): T {
return x
}
type res = typeof fn; // type res = <T>(x: T) => T
对枚举使用typeof
在TypeScript中,enum是一种新的数据类型,但在具体运行的时候,它会被编译成对象。
enum UserResponse {
No = 0,
Yes = 1,
}
对应编译的JavaScript代码为:
var UserResponse;
(function (UserResponse) {
UserResponse[UserResponse["No"] = 0] = "No";
UserResponse[UserResponse["Yes"] = 1] = "Yes";
})(UserResponse || (UserResponse = {}));
如果我们打印一下UserResponse
:
// log:{ '0': 'No', '1': 'Yes', No: 0, Yes: 1 }
如果我们对UserResponse
使用typeof
:
enum UserResponse {
No = 0,
Yes = 1,
}
type n = typeof UserResponse
// n类型类似于
// {
// "No": number,
// "YES": number
// }
不过对一个enum
类型只使用 typeof
一般没什么用,通常还会搭配 keyof
操作符用于获取属性名的联合字符串:
enum UserResponse {
No = 0,
Yes = 1,
}
type n = keyof typeof UserResponse; // type n = "No" | "Yes"