简体   繁体   English

如何强制映射类型具有字符串文字中的所有键

[英]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的情况。

See playground 看游乐场

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;
}>

Typescript playground Typescript 操场

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 .据我了解,您还需要确保AbooleanBnumberCstring 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",
}> 

enter link description here在此处输入链接描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeScript:强制字符串文字类型仅具有一个值 - TypeScript: enforce string literal type to have only one value TypeScript 映射类型以表示具有可选 Observables 的 object(使用字符串文字映射键) - TypeScript mapped type to represent an object with optional Observables (with string literal mapped keys) 打字稿:强制类型为“字符串文字”而不是<string> - Typescript: Enforce a type to be "string literal" and not <string> 如何将字符串文字类型转换为新类型的键? - How to convert a string literal type to the keys of a new type? 如何在 typescript 中将元组元素用作映射类型或模板文字中的键? - How can you use Tuple elements as keys in a Mapped Type or template literal in typescript? 如何从对象创建模板文字类型以具有键=值? - How to create a template literal type from object to have keys=values? 强制 object 包含枚举的所有键,并且仍然对其值进行类型推断 - Enforce object to contain all keys of an enum and still have type inference for it's values 使用映射类型递归获取所有键 - Recursively get all keys using mapped type 确保字符串联合具有特定字符串文字元素的映射类型 - mapped type that ensures a string union has an element of a specific string literal 是否可以通过 Typescript 中的映射类型将文字对象中的值(不是键)作为文字而不是其类型(例如字符串)获取? - Is it possible to get the value (not key) in a literal object as a literal, not its type (such as string) via mapped type in Typescript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM