TypeScript中的“ keyof typeof”是什么意思?

时间:2019-03-27 12:36:38

标签: typescript

示例:

向我解释keyof typeof在TypeScript中的含义

enum ColorsEnum {
    white = '#ffffff',
    black = '#000000',
}

type Colors = keyof typeof ColorsEnum;

最后一行等效于:

type Colors = "white" | "black"

但是它如何工作?

我希望typeof ColorsEnum返回类似"Object"的内容,然后返回keyof "Object"不做任何有趣的事情。但是我显然是错的。

5 个答案:

答案 0 :(得分:105)

要了解打字稿中keyof typeof的用法,首先您需要了解什么是文字类型文字类型联合。因此,我将首先解释这些概念,然后分别详细解释keyoftypeof。之后,我将回到enum来回答问题中的要求。这个答案很长,但是示例很容易理解。


文学类型

Typescript中的文字类型是stringnumberboolean的更具体的类型。例如,"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 与 TypeScript 类型

typeof 在 javascript 对象上调用时的行为与在 typescript 类型上调用时的行为不同。

  • TypeScript 在运行时调用 javascript 值时使用 javascript's typeof 并返回 "undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function" 之一
  • TypeScript's typeof 在类型值上调用,但也可以在类型表达式中的 javascript 值上调用。它还可以推断 javascript 对象的类型,返回更详细的对象类型。
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 typeof

因为 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"

通过将typeofkeyof一起使用,我们可以在对 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之类的用户密钥,则会收到错误消息 “用户”是指一个值,但此处被用作类型。您是说“用户类型”吗?