要了解keyof typeof
在 TypeScript 中的用法,首先你需要了解什么是文字类型 and 文字类型的联合。所以,我会先解释这些概念,然后再解释keyof
and typeof
分别详细说明。之后我会回来enum
回答问题中提出的问题。这是一个很长的答案,但示例很容易理解。
文字类型
TypeScript 中的文字类型是更具体的类型string
, number
or boolean
。例如,"Hello World"
is a string
, but a string
is not "Hello World"
. "Hello World"
是一种更具体的类型string
,所以它是一个文字类型。
文字类型可以声明如下:
type Greeting = "Hello"
这意味着该类型的对象Greeting
只能有一个string
value "Hello"
没有其他string
value 或任何其他类型的任何其他值,如以下代码所示:
let greeting: Greeting
greeting = "Hello" // OK
greeting = "Hi" // Error: Type '"Hi"' is not assignable to type '"Hello"'
文字类型本身并没有什么用处,但是当与联合类型、类型别名和类型保护结合使用时,它们就会变得强大。
以下是一个示例文字类型的联合:
type Greeting = "Hello" | "Hi" | "Welcome"
现在类型的对象Greeting
可以有值"Hello"
, "Hi"
or "Welcome"
.
let greeting: Greeting
greeting = "Hello" // OK
greeting = "Hi" // OK
greeting = "Welcome" // OK
greeting = "GoodEvening" // Error: Type '"GoodEvening"' is not assignable to type 'Greeting'
keyof
only
keyof
某种类型的T
给你一个新的类型文字类型的联合这些文字类型是属性的名称T
。结果类型是字符串的子类型。
例如,考虑以下情况interface
:
interface Person {
name: string
age: number
location: string
}
使用keyof
类型上的运算符Person
将为您提供一个新类型,如以下代码所示:
type SomeNewType = keyof Person
This SomeNewType
是文字类型的联合 ("name" | "age" | "location"
) 由类型的属性组成Person
.
现在您可以创建类型的对象SomeNewType
:
let newTypeObject: SomeNewType
newTypeObject = "name" // OK
newTypeObject = "age" // OK
newTypeObject = "location" // OK
newTypeObject = "anyOtherValue" // Error...
keyof typeof
一起在一个物体上
您可能已经知道,typeof
运算符给出对象的类型。
在上面的例子中Person
接口,我们已经知道类型,所以我们只需要使用keyof
类型运算符Person
.
但是,当我们不知道对象的类型或者我们只有一个值而不是该值的类型时该怎么办,如下所示?
const bmw = { name: "BMW", power: "1000hp" }
这是我们使用的地方keyof typeof
一起。
The typeof bmw
给你类型:{ name: string, power: string }
进而keyof
运算符为您提供文字类型联合,如以下代码所示:
type CarLiteralType = keyof typeof bmw
let carPropertyLiteral: CarLiteralType
carPropertyLiteral = "name" // OK
carPropertyLiteral = "power" // OK
carPropertyLiteral = "anyOther" // Error...
keyof typeof
on an enum
在 TypeScript 中,枚举用作编译时的类型实现常量的类型安全,但它们被视为运行时的对象。这是因为,一旦 TypeScript 代码被编译为 JavaScript,它们就会转换为普通对象。因此,上述对象的解释也适用于这里。 OP在问题中给出的例子是:
enum ColorsEnum {
white = '#ffffff',
black = '#000000',
}
Here ColorsEnum
在运行时作为对象而不是类型存在。所以,我们需要调用keyof typeof
运算符组合在一起,如以下代码所示:
type Colors = keyof typeof ColorsEnum
let colorLiteral: Colors
colorLiteral = "white" // OK
colorLiteral = "black" // OK
colorLiteral = "red" // Error...