要了解keyof typeof
TypeScript 中的用法,首先需要了解什么是字面量类型和字面量类型的联合。因此,我将首先解释这些概念,然后再keyof
详细解释typeof
。之后,我会回来enum
回答问题中的问题。这是一个很长的答案,但例子很容易理解。
文字类型
TypeScript 中的文字类型是更具体的string
,number
或boolean
. 例如,"Hello World"
is a string
,但 a string
is not "Hello World"
。"Hello World"
是 type 的一种更具体的类型string
,所以它是一个字面量类型。
文字类型可以声明如下:
type Greeting = "Hello"
这意味着类型的对象Greeting
只能有一个string
值"Hello"
,而不能有其他string
值或任何其他类型的任何其他值,如以下代码所示:
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"
或者"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
只要
keyof
of some typeT
给你一个新类型,它是文字类型的联合,这些文字类型是T
. 结果类型是字符串的子类型。
例如,考虑以下内容interface
:
interface Person {
name: string
age: number
location: string
}
在类型上使用keyof
运算符Person
将为您提供一个新类型,如以下代码所示:
type SomeNewType = keyof Person
这是由 type 的属性组成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
在 type 上使用运算符Person
。
但是当我们不知道对象的类型或者我们只有一个值而不是像下面这样的值的类型时该怎么办?
const bmw = { name: "BMW", power: "1000hp" }
这是我们keyof typeof
一起使用的地方。
为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
在一个enum
在 TypeScript 中,枚举在编译时用作类型以实现常量的类型安全,但它们在运行时被视为对象。这是因为,一旦将 TypeScript 代码编译为 JavaScript,它们就会转换为普通对象。因此,上述对象的解释也适用于此。OP在问题中给出的示例是:
enum ColorsEnum {
white = '#ffffff',
black = '#000000',
}
这里ColorsEnum
在运行时作为对象存在,而不是作为类型存在。因此,我们需要一起调用keyof typeof
运算符,如下代码所示:
type Colors = keyof typeof ColorsEnum
let colorLiteral: Colors
colorLiteral = "white" // OK
colorLiteral = "black" // OK
colorLiteral = "red" // Error...
而已!希望有帮助。