从字符串列表中导出类型A.

时间:2017-09-27 10:08:03

标签: list typescript converter

假设我有一个常量且不可变的字符串列表a

const a = ['b', 'c', 'd']

我想创建一个如下所示的类型A:

type A = 'b' | 'c' | 'd'

我的问题是:如何自动从列表A创建类型a

另一种方式对我也有用:如何在类型a

的情况下创建列表A

2 个答案:

答案 0 :(得分:1)

,您可以这样做。唯一的障碍是,如果你写

const a = ['b','c','d'];
// inferred as string[]

然后a将被推断为string[],因此当您尝试推导时,文字值'a''b''c'会被遗忘A。您始终可以明确注释a的类型:

const a: ['b','c','d'] = ['b','c','d'];
type A = typeof a[number];
//type A = "b" | "c" | "d"

但现在你正在重复自己,你正试图避免。有一个解决方案:

an answer to another question中,我推荐了一个辅助函数(tuple.ts中的tuple())来推断元组类型。

const a = tuple('b','c','d');
//inferred as type ["b", "c", "d"]

type A = typeof a[number]; 
//type A = "b" | "c" | "d"

如果你不关心它是一个元组,你可以编写一个简单的数组推理辅助函数:

function inferLiteralArray<T extends string>(...arr: T[]): T[] {
  return arr;
}

const a = inferLiteralArray("b", "c", "d");
//inferred as type ("b" | "c" | "d")[]

type A = typeof a[number];
//type A = "b" | "c" | "d"

无论哪种方式都有效,而且你不需要重复自己。希望有所帮助;祝你好运!

更新1

@fritz_da_silva said

  

太棒了,它工作得很整齐! a [number]语法对我来说就像黑魔法。你能详细说明它的工作原理吗?

不确定。语法应该像这样解释(为了清楚起见,请参阅我添加的括号):

type A = (typeof a)[number];

typeof a部分正在使用typeof type query operator获取a的类型,(tuple()示例)为["b", "c", "d"]

然后我使用indexed access operator。如果您的键之一<{1}}类型T (因此它应该扩展K;您可以使用{{1}等字符串文字或者像keyof T这样的数字文字或这些的联合),然后"length"是该密钥可访问的属性的类型。对于arraylike类型0,类型T[K]获取该数组类型的元素类型。在元组示例中,这结果是一个联合,因为有多个类型A的键具有不同的属性类型。 (当您使用索引访问运算符时,A[number]应等于number)。观察:

T[K1|K2]

这有意义吗?

答案 1 :(得分:0)

由于数组是在运行时创建的,因此无法执行您想要执行的操作,并且编译器无法确定对数组的更改。因此,它无法强制执行类型系统。

例如,请考虑以下事项:

const array = [ "Bob", "James", "Dan" ];
let value: *A key of array*
setTimeout(() => {
    value = "James";
}, 1000);
array.splice(1, 1);

上述情况会发生什么?在调用value = "James时,"James"已从数组中删除,因此应该抛出错误!但这在运行时发生,因此编译器无法向您发出警告。

解决方法是使用以下构造声明一个类型,但不能修改它:

type MyType = "Bob" | "James" | "Dan"
let value: MyType = "Dan";
value = "Steven" // <- Compiler error!

编辑:saravana在评论中快速总结。