I am trying to get a string literal union based on values passed to an array of classes via constructor.
For example, the array looks like this:
const myArray = [
new MyClass({
key: "key1",
}),
new MyClass({
key: "key2",
}),
]
And I'm trying to construct a mapped version of it (for lookup) or a string literal union:
type MyUnionType = "key1" | "key2"
The primary reason for this is to ensure that any lookups use available keys assigned to the class.
getClass('key1') // all good
getClass('notAKey') // error
However all solutions I've seen so far include some form of redundancy in either passing the key as a generic or creating an object with the same keys.
You can do something like this:
type MyUnionType = {
[K in keyof typeof myArray]:
(typeof myArray)[K] extends MyClass<infer T> ? T : never
}[number]
This is a mapped type that goes over each key in the array, and then infers the generic parameter from each member of myArray
.
This assumes a class like:
class MyClass<T extends string> {
constructor(options: { key: T }) {}
}
Which you would use like:
const myArray = [
new MyClass({
key: "key1",
}),
new MyClass({
key: "key2",
}),
] as const
function getClass(input: MyUnionType) {}
getClass('key1') // works
getClass('notAKey') // error
Or, parameterized for more flexibility:
type MyUnionType<T extends readonly MyClass<string>[]> = {
[K in keyof T]:
T[K] extends MyClass<infer U> ? U : never
}[number]
function getClass(input: MyUnionType<typeof myArray>) {}
getClass('key1') // works
getClass('notAKey') // error
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.