К сожалению, вы в основном хотите ограничить тип переменной и в то же время заставить компилятор выводить тип для этой переменной. Это, к сожалению, невозможно напрямую.
Единственный способ добиться желаемого поведения - это использовать функцию. У функций могут быть параметры универсального типа, на которые наложены ограничения, но окончательный параметр типа будет выведен из фактического литерала объекта, переданного в:
type QueryRequest<T, K extends keyof T> = {
keys: Record<K, boolean>
}
function buildQueryRequest<T>() {
return function <P extends keyof T> (o:Partial<Record<P, boolean>>) : QueryRequest<T, P>{
return null!;
}
}
interface IFood {
name: string;
nodeId: number;
}
type QueryResult<T, K extends keyof T> = Pick<T, K>
declare class Client {
food<K extends keyof IFood>(q: QueryRequest<IFood, K>) : Promise<QueryResult<IFood, K>>
}
(async function (client: Client) {
const query = buildQueryRequest<IFood>()({
name: true // true ==> implies inclusion in response
})
const res = await client.food(query)
console.log(res.name) // PASS - should compile
console.log(res.nodeId) // error
})
buildQueryRequest
- это функция, которая возвращает функцию (т. Е. Каррированную функцию), чтобы можно было указывать первый аргумент и выводить второй,