示例:
向我解释keyof typeof
在TypeScript中的含义
enum ColorsEnum {
white = '#ffffff',
black = '#000000',
}
type Colors = keyof typeof ColorsEnum;
最后一行等效于:
type Colors = "white" | "black"
但是它如何工作?
我希望typeof ColorsEnum
返回类似"Object"
的内容,然后返回keyof "Object"
不做任何有趣的事情。但是我显然是错的。
答案 0 :(得分:105)
要了解打字稿中keyof typeof
的用法,首先您需要了解什么是文字类型和文字类型联合。因此,我将首先解释这些概念,然后分别详细解释keyof
和typeof
。之后,我将回到enum
来回答问题中的要求。这个答案很长,但是示例很容易理解。
Typescript中的文字类型是string
,number
或boolean
的更具体的类型。例如,"Hello World"
是string
,但是string
不是"Hello World"
。 "Hello World"
是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
的 T
为您提供了一个新类型,它是文本类型的联合,这些文本类型是{{1} }。结果类型是字符串的子类型。
例如,考虑以下T
:
interface
在类型interface Person {
name: string
age: number
location: string
}
上使用keyof
运算符将为您提供一个新的类型,如以下代码所示:
Person
此type SomeNewType = keyof Person
是文字类型(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
为您提供类型: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
上在Typescript中,枚举是真实的对象。因此,以上对象的说明也适用于此。 OP在问题中给出的示例是:
enum
enum ColorsEnum {
white = '#ffffff',
black = '#000000',
}
是对象,而不是类型。因此,我们需要一起调用ColorsEnum
运算符,如以下代码所示:
keyof typeof
就是这样!希望有帮助。
答案 1 :(得分:27)
keyof
接受一个对象类型并返回一个接受任何对象键的类型。
type Point = { x: number; y: number };
type P = keyof Point; // type '"x" || "y"'
const coordinate: P = 'z' // Type '"z"' is not assignable to type '"x" | "y"'.
typeof
在 javascript 对象上调用时的行为与在 typescript 类型上调用时的行为不同。
"undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function"
之一type Language = 'EN' | 'ES';
const userLanguage: Language = 'EN';
const preferences = { language: userLanguage, theme: 'light' };
console.log(typeof preferences); // "object"
type Preferences = typeof preferences; // type '{language: 'EN''; theme: string; }'
因为第二个 typeof preferences
在类型表达式中,所以它实际上是 TypeScript 自己的 typeof
被调用,而不是 javascript 的。
因为 keyof
是一个 TypeScript 概念,所以我们将调用 TypeScript 的 typeof
版本。
keyof typeof
将推断 javascript 对象的类型并返回其键的联合类型。因为它可以推断出键的确切值,所以它可以返回它们的 literal types 的并集,而不仅仅是返回“字符串”。
type PreferenceKeys = keyof typeof preferences; // type '"language" | "theme"'
答案 2 :(得分:9)
关于TypeScript的常见误解
TypeScript通常被描述为JavaScript运行时之上的类型层。好像类型和值位于不同的平面上。但是,在TypeScript中,有些东西同时是类型和的值。
这适用于:
何时可以使用keyof
?
keyof
关键字仅适用于类型级别。您不能将其应用于JavaScript值。
何时需要keyof typeof
?
当您同时处理类型和值(例如类或枚举)时,但是您特别对值的类型感兴趣。
最简单的例子:
const foo = { bar: 42 }; // foo is a value
type Foo = typeof foo; // Foo is the type of foo
type KeyOfFoo = keyof Foo; // "keyof Foo" is the same as "keyof typeof foo", which is "bar"
通常,当您看到以下内容时:
type A = keyof typeof B;
typeof B
部分告诉TypeScript查看B的 type 。您可以将其视为将B强制转换为其类型。有点像将二维对象投射到一维空间。
由于typeof B
是类型而不是值,因此我们现在可以在其上使用keyof
。
示例
类是类型和值。您可以呼叫它们,但也可以在它们上使用keyof
。
declare class Foo {
static staticProperty: string;
dynamicProperty: string;
}
type Constructor = typeof Foo;
type Instance = Foo;
type A = keyof Constructor; // "prototype" | "staticProperty"
type B = keyof Instance; // "dynamicProperty"
通过将typeof
与keyof
一起使用,我们可以在对 instance 类型和 constructor 类型使用keyof
之间切换
答案 3 :(得分:5)
一个enum
创建一个实例化的object
。使用typeof
,我们可以自动生成此enum
的类型。
现在,我们可以使用keyof
获取所有索引,以确保Colors
只能包含其中一个。
答案 4 :(得分:0)
要查找任何值的类型,我们使用typeof操作。对于例如
const user = {
getPersonalInfo(){},
getLocation(){}
}
这里的用户是一个值,因此typeof运算符很方便
type userType = typeof user
在此,userType给出类型信息,即user是一个对象,它具有两个属性getPersonalInfo和getLocation,并且都是返回void的函数
现在,如果要查找用户的密钥,可以使用keyof
type userKeys = keyof userType
其中显示userKeys = 'getPersonalInfo'| 'getLocation'
当心,如果您尝试获取
type userKeys = keyof user
之类的用户密钥,则会收到错误消息 “用户”是指一个值,但此处被用作类型。您是说“用户类型”吗?