是否可以将 Map 键提取为 TypeScript 中的类型?
Is it possible to extract Map keys as type in TypeScript?
在 TypeScript 中你可以做到
const obj = {
'123-123': 1,
'456-456': 2,
}
type objKeys = keyof typeof obj
而objKeys
是联合类型'123-123' | '456-456'
。
如果 obj
不是一个对象,而是一个地图,是否有类似的可能?
const map = new Map<string, number>([
['123-123', 1],
['456-456', 2],
])
type mapKeys = ???
如果你写 new Map<string, number>(...)
那么你明确地给 Map
一个 string
键类型,这意味着它将允许你 set()
和 get()
和 string-valued 键。如果您想将键限制为特定的 union of string literal types,那么您将需要更改构造 Map
的方式。比如你提前定义了MapKeys
,就可以用它来代替string
:
type MapKeys = '123-123' | '456-456';
const map = new Map<MapKeys, number>([
['123-123', 1],
['456-456', 2],
]);
但这有点多余,而且与您的要求相反。您希望编译器根据传递给 Map
构造函数的参数 推断 MapKeys
。
既然你说用例是 Map
是常量(因此不仅它的键受到约束,而且它的值也不会改变),那么 [= 可能会更好地为你服务40=] 由 TypeScript 提供。在运行时没有 ReadonlyMap
,但 TypeScript 编译器将允许您将 Map
实例分配给 ReadonlyMap
.
类型的变量
并且如果我们希望编译器推断MapKeys
,我们可能希望constrain构造函数的键类型为string
,这给编译器一个提示strings.
这两个都意味着在 K
被限制为 string
的情况下创建新 ReadonlyMap<K, V>
的辅助函数将有所帮助:
function ReadonlyMapWithStringKeys<K extends string, V>(
iterable: Iterable<[K, V]>): ReadonlyMap<K, V> {
return new Map(iterable)
}
const map = ReadonlyMapWithStringKeys([
['123-123', 1],
['456-456', 2],
])
// const map: ReadonlyMap<"123-123" | "456-456", number>
现在我们可以看到map
是一个键是强类型的类型。我们现在可以从中定义 MapKeys
。有多种方法可以做到这一点;一个正在使用 conditional type inference with the infer
keyword
type MapKeys = typeof map extends ReadonlyMap<infer K, any> ? K : never;
// type MapKeys = "123-123" | "456-456"
或者您可以使用 the Parameters<T>
type 等实用程序类型来询问编译器 map.get()
的第一个参数是什么:
type MapKeys = Parameters<typeof map["get"]>[0]
// type MapKeys = "123-123" | "456-456"
在 TypeScript 中你可以做到
const obj = {
'123-123': 1,
'456-456': 2,
}
type objKeys = keyof typeof obj
而objKeys
是联合类型'123-123' | '456-456'
。
如果 obj
不是一个对象,而是一个地图,是否有类似的可能?
const map = new Map<string, number>([
['123-123', 1],
['456-456', 2],
])
type mapKeys = ???
如果你写 new Map<string, number>(...)
那么你明确地给 Map
一个 string
键类型,这意味着它将允许你 set()
和 get()
和 string-valued 键。如果您想将键限制为特定的 union of string literal types,那么您将需要更改构造 Map
的方式。比如你提前定义了MapKeys
,就可以用它来代替string
:
type MapKeys = '123-123' | '456-456';
const map = new Map<MapKeys, number>([
['123-123', 1],
['456-456', 2],
]);
但这有点多余,而且与您的要求相反。您希望编译器根据传递给 Map
构造函数的参数 推断 MapKeys
。
既然你说用例是 Map
是常量(因此不仅它的键受到约束,而且它的值也不会改变),那么 [= 可能会更好地为你服务40=] 由 TypeScript 提供。在运行时没有 ReadonlyMap
,但 TypeScript 编译器将允许您将 Map
实例分配给 ReadonlyMap
.
并且如果我们希望编译器推断MapKeys
,我们可能希望constrain构造函数的键类型为string
,这给编译器一个提示strings.
这两个都意味着在 K
被限制为 string
的情况下创建新 ReadonlyMap<K, V>
的辅助函数将有所帮助:
function ReadonlyMapWithStringKeys<K extends string, V>(
iterable: Iterable<[K, V]>): ReadonlyMap<K, V> {
return new Map(iterable)
}
const map = ReadonlyMapWithStringKeys([
['123-123', 1],
['456-456', 2],
])
// const map: ReadonlyMap<"123-123" | "456-456", number>
现在我们可以看到map
是一个键是强类型的类型。我们现在可以从中定义 MapKeys
。有多种方法可以做到这一点;一个正在使用 conditional type inference with the infer
keyword
type MapKeys = typeof map extends ReadonlyMap<infer K, any> ? K : never;
// type MapKeys = "123-123" | "456-456"
或者您可以使用 the Parameters<T>
type 等实用程序类型来询问编译器 map.get()
的第一个参数是什么:
type MapKeys = Parameters<typeof map["get"]>[0]
// type MapKeys = "123-123" | "456-456"