[英]How to enforce mapped type to have all of the keys in a string literal
Given the following list:给定以下列表:
const list = ["A", "B", "C"] as const;
type List = typeof list[number];
I have a map that must have all of the possible keys of list
:我有一个 map 必须具有list
的所有可能键:
const mapping: Record<List, unknown> = {
A: true,
B: 2,
C: "three"
};
Just like I could enforce mapping
to map over List
, I would like to do the same for a type.就像我可以通过List
强制mapping
到 map 一样,我想对类型做同样的事情。 Something like this (I'm aware it's an invalid syntax):像这样的东西(我知道这是一个无效的语法):
type MappedList: Record<List, unknown> = {
A: boolean,
B: number,
C: string
}
My main goal is to prevent a situation when I add a new cell into list
and forget to add it to MappedList
.我的主要目标是防止出现我将新单元格添加到list
而忘记将其添加到MappedList
的情况。
You can do this by creating a utility that would require generics to match:您可以通过创建一个需要 generics 匹配的实用程序来做到这一点:
type AssertKeysEqual<
T1 extends Record<keyof T2, any>,
T2 extends Record<keyof T1, any>
> = T2
const list = ["A", "B", "C"] as const;
type ListKey = typeof list[number];
const mapping: Record<ListKey, unknown> = {
A: true,
B: 2,
C: "three",
};
type MappedList = AssertKeysEqual<Record<ListKey, unknown>, {
A: boolean;
B: number;
C: string;
}>
AFAIK, there is not such concept as type for type. AFAIK,没有类型的类型这样的概念。 However, you can use mapped types to create one type from another.但是,您可以使用映射类型从另一种类型创建一种类型。
const list = ["A", "B", "C"] as const;
type ListKey = typeof list[number];
// type MappedList = {
// A: "property";
// B: "property";
// C: "property";
// }
type MappedList = {
[Prop in ListKey]: 'property'
}
As far as I understood, you also need to assure that A
is a boolean
, B
is a number
and C
is a string
.据我了解,您还需要确保A
是boolean
, B
是number
, C
是string
。 In order to do it, you need create a map and conditional type:为此,您需要创建一个 map 和条件类型:
const list = ["A", "B", "C"] as const;
type ListKey = typeof list[number];
type TypeMap = {
A: boolean,
B: number,
C: string
};
/**
* If T is a subtype of TypeMap
* and keyof T extends keyof TypeMap
*/
type BuildMappedList<T> = T extends TypeMap ? keyof T extends keyof TypeMap ? T : never : never;
/**
* Ok
*/
type MappedList = BuildMappedList<{
A: true,
B: 2,
C: "three",
}>
/**
* Never
*/
type MappedList2 = BuildMappedList<{
A: true,
B: 2,
C: "three",
D: [2] // because of extra D property
}>
/**
* Never
*/
type MappedList3 = BuildMappedList<{
B: 2,
C: "three",
}> // because no A property
/**
* Never
*/
type MappedList4 = BuildMappedList<{
A: false,
B: [2], // because B is not a number
C: "three",
}>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.