可以使用数组值来创建具有相应字符串文字的键值类型吗?
Possible to use array values to create key-value type with corresponding string literals?
//### Desired Implementation & Outcome: ###//
function objectFromArray<T extends string[]>(...arr:T){
return {/* do things */} as ObjectFromArray<T>
}
const foo = objectFromArray("a", "b", "c")
// foo === {a:"a", b:"b", c:"c"}
// typeof foo.a === "a"
// typeof foo.b === "b"
// typeof foo.c === "c"
//### Attempt 1: ###//
type ObjectFromArray<T extends any[]> = {[K in T[number]]: T[number]}
// no error, but results in unions instead of single values:
// typeof foo.a === ("a" | "b" | "c")
// typeof foo.b === ("a" | "b" | "c")
// typeof foo.c === ("a" | "b" | "c")
//### Attempt 2: ###//
type ObjectFromArray<T extends string[]> = {[K in T[number]]: T[number][K]}
// Error: Type 'K' cannot be used to index type 'T[number]'.ts(2536)
希望这就是你的意思:
function objectFromArray<T extends string[]>(...arr:T){
return {/* do things */} as ObjectFromArray<T>
}
type ObjectFromKeyList<KeyList extends string> = {[K in KeyList]: K}
type ArrayToKeyList<T extends any[]> = T extends (infer P)[] ? P : never
type ObjectFromArray<T extends any[]> = ObjectFromKeyList<ArrayToKeyList<T>>
const foo = objectFromArray("a", "b", "c")
foo.a // type is 'a'
//### Desired Implementation & Outcome: ###//
function objectFromArray<T extends string[]>(...arr:T){
return {/* do things */} as ObjectFromArray<T>
}
const foo = objectFromArray("a", "b", "c")
// foo === {a:"a", b:"b", c:"c"}
// typeof foo.a === "a"
// typeof foo.b === "b"
// typeof foo.c === "c"
//### Attempt 1: ###//
type ObjectFromArray<T extends any[]> = {[K in T[number]]: T[number]}
// no error, but results in unions instead of single values:
// typeof foo.a === ("a" | "b" | "c")
// typeof foo.b === ("a" | "b" | "c")
// typeof foo.c === ("a" | "b" | "c")
//### Attempt 2: ###//
type ObjectFromArray<T extends string[]> = {[K in T[number]]: T[number][K]}
// Error: Type 'K' cannot be used to index type 'T[number]'.ts(2536)
希望这就是你的意思:
function objectFromArray<T extends string[]>(...arr:T){
return {/* do things */} as ObjectFromArray<T>
}
type ObjectFromKeyList<KeyList extends string> = {[K in KeyList]: K}
type ArrayToKeyList<T extends any[]> = T extends (infer P)[] ? P : never
type ObjectFromArray<T extends any[]> = ObjectFromKeyList<ArrayToKeyList<T>>
const foo = objectFromArray("a", "b", "c")
foo.a // type is 'a'