Preface
The official documentation of TypeScript has long been updated, but the Chinese documents I can find are still in the older version. Therefore, some new and revised chapters have been translated and sorted out.
This article is organized from the " Keyof Type Operator " chapter in the TypeScript Handbook.
This article does not strictly follow the original translation, but also explains and supplements part of the content.
keyof
type operator
keyof
operator for an object type will return a string or combination of numeric literals composed of the object's attribute name. The type P in this example is equivalent to "x" | "y":
type Point = { x: number; y: number };
type P = keyof Point;
// type P = keyof Point
But if this type has an index signature of type string
or number
keyof
will directly return these types:
type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish;
// type A = number
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
// type M = string | number
Note that in this example, M
is string | number
. This is because the property name of the JavaScript object will be forced to a string, so obj[0]
and obj["0"]
are the same.
(Note: The original text ends here)
Number literal union type
At the beginning we also said that keyof
may also return a numeric literal union type. When will the numeric literal union type be returned? We can try to construct such an object:
const NumericObject = {
[1]: "冴羽一号",
[2]: "冴羽二号",
[3]: "冴羽三号"
};
type result = keyof typeof NumericObject
// typeof NumbericObject 的结果为:
// {
// 1: string;
// 2: string;
// 3: string;
// }
// 所以最终的结果为:
// type result = 1 | 2 | 3
Symbol
In fact, TypeScript can also support symbol type attribute names:
const sym1 = Symbol();
const sym2 = Symbol();
const sym3 = Symbol();
const symbolToNumberMap = {
[sym1]: 1,
[sym2]: 2,
[sym3]: 3,
};
type KS = keyof typeof symbolToNumberMap; // typeof sym1 | typeof sym2 | typeof sym3
This is why when we use generics like the following example, we will report an error like this:
function useKey<T, K extends keyof T>(o: T, k: K) {
var name: string = k;
// Type 'string | number | symbol' is not assignable to type 'string'.
}
If you are sure to use only string type attribute names, you can write:
function useKey<T, K extends Extract<keyof T, string>>(o: T, k: K) {
var name: string = k; // OK
}
And if you want to process all attribute names, you can write:
function useKey<T, K extends keyof T>(o: T, k: K) {
var name: string | number | symbol = k;
}
Classes and interfaces
keyof
for the class:
// 例子一
class Person {
name: "冴羽"
}
type result = keyof Person;
// type result = "name"
// 例子二
class Person {
[1]: string = "冴羽";
}
type result = keyof Person;
// type result = 1
keyof
for the interface:
interface Person {
name: "string";
}
type result = keyof Person;
// type result = "name"
Actual combat
In the "Generic 161d45cad52be1 TypeScript", an application of keyof
We want to get the value of a given attribute name of an object. For this, we need to make sure that we don't get obj
that don't exist on 061d45cad52bf6. So we establish a constraint between the two types:
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a");
getProperty(x, "m");
// Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.
In the following " Mappred Types " chapter, we will also talk about keyof
.
TypeScript series
The TypeScript series of articles consists of three parts: official document translation, important and difficult analysis, and practical skills. It covers entry, advanced, and actual combat. It aims to provide you with a systematic learning TS tutorial. The entire series is expected to be about 40 articles. Click here to browse the full series of articles, and suggest to bookmark the site by the way.
WeChat: "mqyqingfeng", add me to the only reader group in Kongyu.
If there are mistakes or not rigorous, please correct me, thank you very much. If you like or have some inspiration, star is welcome, which is also an encouragement to the author.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。