是的,这是可能的。我自己并没有想出这个解决方案,所以所有的功劳都归于 github 上的“drop-george”人:
type User = {
a: number;
b: number;
c: number;
}
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
infer ElementType
>
? ElementType
: never
function get<T, K extends (keyof T)[]>(v: T, keys: K): Pick<T, ElementType<K>> {
return v
}
const user: User = {a: 1, b: 2, c: 3}
const v = get(user, ['a', 'b'])
const {a, b, c} = v // ERROR
const {a: a2, b: b2} = v // OK
const {a: a3} = v // OK
get({a: 1, b: 2, c: 3} as User, ['a', 'b', 'otherKey']) // ERROR
Original source
UPD:您可以只使用ElementType<K> 而不是ElementType<typeof keys>
UPD2:AFAIK 如果你想制作类似fun<User>(['firstName', 'lastName']) 的东西,唯一的两种方法是:
function get<T, K extends (keyof T)[]>(keys: K): Pick<T, ElementType<K>> {
// return user
}
const user = get<User, ['firstName', 'lastName']>(['firstName', 'lastName'])
function get<T>(): <K extends (keyof T)[]>(keys: K) => Pick<T, ElementType<K>> {
return keys => {
// return user from db
}
}
const user = get<User>()(['firstName', 'lastName'])