我目前有一个字符串数组和一个包含相同字符串的字符串字面量联合类型:
const furniture = ['chair', 'table', 'lamp'];
type Furniture = 'chair' | 'table' | 'lamp';
我需要在应用程序中同时使用它们,但我想保持我的代码DRY。那么有没有办法从一个中推断出另一个?
基本上我想说类似于type Furniture = [furniture数组中的任何字符串]
,这样就不会有重复的字符串了。
我目前有一个字符串数组和一个包含相同字符串的字符串字面量联合类型:
const furniture = ['chair', 'table', 'lamp'];
type Furniture = 'chair' | 'table' | 'lamp';
我需要在应用程序中同时使用它们,但我想保持我的代码DRY。那么有没有办法从一个中推断出另一个?
基本上我想说类似于type Furniture = [furniture数组中的任何字符串]
,这样就不会有重复的字符串了。
有了这种新语法,我们可以得到一个简洁明了的解决方案:
const furniture = ['chair', 'table', 'lamp'] as const;
type Furniture = typeof furniture[number];
关于新const上下文的更多内容可以在此PR中找到,以及发行说明中。
使用泛型rest参数,有一种方法可以正确地推断string[]
为一个文字元组类型,然后获得文字联合类型。
步骤如下:
const tuple = <T extends string[]>(...args: T) => args;
const furniture = tuple('chair', 'table', 'lamp');
type Furniture = typeof furniture[number];
最佳可用解决方法:
const furnitureObj = { chair: 1, table: 1, lamp: 1 };
type Furniture = keyof typeof furnitureObj;
const furniture = Object.keys(furnitureObj) as Furniture[];
理想情况下,我们可以这样做:
const furniture = ['chair', 'table', 'lamp'];
type Furniture = typeof furniture[number];
很不幸,今天furniture
被推断为string[]
,这意味着Furniture
现在也是一个string
。
我们可以通过手动注释来强制类型为文字,但它会带来重复:
const furniture = ["chair", "table", "lamp"] as ["chair", "table", "lamp"];
type Furniture = typeof furniture[number];
TypeScript issue #10195 追踪指示给TypeScript的列表应被推断为静态元组而不是string[]
,因此也许将来这将成为可能。
在TypeScript 3.4中,最简单的方法是使用常量断言(const assertions):
(请注意,TypeScript 3.4添加了常量断言)const furniture = ["chair", "table", "lamp"] as const;
type Furniture = typeof furniture[number]; // "chair" | "table" | "lamp"
参见https://dev59.com/0lQK5IYBdhLWcg3wSeK9#55505556
或者,如果你把这些键作为对象的属性,你也可以将其转换为联合类型:
const furniture = {chair:{}, table:{}, lamp:{}} as const;
type Furniture = keyof typeof furniture; // "chair" | "table" | "lamp"
const
与类型保证兼容,像这样:type Furniture = 'chair' | 'table' | 'lamp';
const furniture: Furniture[] = ['chair', 'table', 'lamp'];
如果您在数组中拼写错误或添加未知项,这将会给您一个警告:
// Warning: Type 'unknown' is not assignable to furniture
const furniture: Furniture[] = ['chair', 'table', 'lamp', 'unknown'];
[number]
的目的是什么?这不是可以推断出来的吗? - robC[number]
的原因是,如果没有它,typeof furniture
将返回一个数组类型。有了索引签名typeof furniture[number]
表示“furniture中任何有效数字索引的类型”,因此您会得到一个值联合类型的类型,而不是一个数组类型。 - Jason Kohlesconst a = ["a", "b", "c"]; const b = a as const;
- 这将抛出以下错误:'const'断言只能应用于对枚举成员、字符串、数字、布尔值、数组或对象文本的引用。
- Slavik Meltseras const
。在你的例子中,在定义a
和定义b
之间可能会插入一个新指令来更改a
,所以我认为这就是 TS 不想信任它的原因。对于我来说,在运行 TS 4.5.2 时,以下代码可以正常工作:const a = ["x", "y", "z"] as const;
//const b = a;
如果我查看b
的 TS 类型,我会得到const b: readonly ["x", "y", "z"]
。 - Erdős-Bacon["a", "b", "c"]
被推断为string[]
。这只是TypeScript设计者做出的选择 - 它也可以是const ["a", "b", "c"]
。选择这种方式的原因是大多数情况下,开发人员想要的是string[]
,这就是为什么如果您想以另一种方式使用它,就需要使用as const
来覆盖它的原因。 - ggradnig