在打字稿中反映和映射类型参数形状?
Reflect and map typed argument shape in typescript?
上下文
我正在尝试构建代码生成工具。我喜欢使用 GraphQL,但是,当我拥有完整的堆栈时,我的前端使用字符串定义的 gql 查询调用我的后端似乎有点愚蠢。 GQL 是强类型的,因此我应该能够提供强类型的查询和响应。
问题
我不知道如何构建一个接口,以便我可以递归地反映和映射参数从输入类型到目标类型。具体来说,我想将我的查询请求类型映射到 gql 查询响应类型。
const query: QueryRequest<Food.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) // FAIL - should not compile. `nodeId` was not present in query
// Food.IFood is a TS interface, representative of my GQL schema. GQL => TS interfaces is a solved codegen problem already
// ref: https://github.com/cdaringe/gql-ts-client-codegen/blob/master/src/__tests__/fixture/namespace.ts
QueryRequest<T>
将我的 Food.IFood
接口(不完全)映射到一个新类型,其中键映射到布尔值,表示包含 GQL 字段
- 但是,每个客户端方法都需要 嗅探 传递的
QueryRequest<T>
以获得显式形状,并以某种方式将该显式形状映射到 [=14] =].
- Cleary 我 不 想要一个
Partial
--Partial
对于存在哪些字段是不明确的。我希望客户端的响应具有明确的字段成员资格,作为输入的函数。
我知道上面对我的 GQL 客户端的描述在很大程度上过于简单化了,并且放弃了与所有 GQL 功能兼容所需的其他复杂性。那很好。我在这个post中的主要objective严格来说是看看有没有办法做这个反射类型映射。
我已经开始草拟一个硬编码的 target client.ts
文件,我希望潜在的输出如下所示:https://github.com/cdaringe/gql-ts-client-codegen/blob/master/src/target.ts
如有任何意见,我们将不胜感激!谢谢。
不幸的是,您基本上想要限制变量的类型,同时让编译器推断该变量的类型。不幸的是,这不可能直接实现。
实现所需行为的唯一方法是使用函数。函数可以具有泛型类型参数,这些类型参数对其施加了约束,但最终类型参数将从传入的实际对象文字中推断出来:
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
是一个函数 returns 一个函数(即柯里化函数),以便允许指定第一个参数和推断第二个参数,
上下文
我正在尝试构建代码生成工具。我喜欢使用 GraphQL,但是,当我拥有完整的堆栈时,我的前端使用字符串定义的 gql 查询调用我的后端似乎有点愚蠢。 GQL 是强类型的,因此我应该能够提供强类型的查询和响应。
问题
我不知道如何构建一个接口,以便我可以递归地反映和映射参数从输入类型到目标类型。具体来说,我想将我的查询请求类型映射到 gql 查询响应类型。
const query: QueryRequest<Food.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) // FAIL - should not compile. `nodeId` was not present in query
// Food.IFood is a TS interface, representative of my GQL schema. GQL => TS interfaces is a solved codegen problem already
// ref: https://github.com/cdaringe/gql-ts-client-codegen/blob/master/src/__tests__/fixture/namespace.ts
QueryRequest<T>
将我的Food.IFood
接口(不完全)映射到一个新类型,其中键映射到布尔值,表示包含 GQL 字段- 但是,每个客户端方法都需要 嗅探 传递的
QueryRequest<T>
以获得显式形状,并以某种方式将该显式形状映射到 [=14] =].- Cleary 我 不 想要一个
Partial
--Partial
对于存在哪些字段是不明确的。我希望客户端的响应具有明确的字段成员资格,作为输入的函数。
- Cleary 我 不 想要一个
我知道上面对我的 GQL 客户端的描述在很大程度上过于简单化了,并且放弃了与所有 GQL 功能兼容所需的其他复杂性。那很好。我在这个post中的主要objective严格来说是看看有没有办法做这个反射类型映射。
我已经开始草拟一个硬编码的 target client.ts
文件,我希望潜在的输出如下所示:https://github.com/cdaringe/gql-ts-client-codegen/blob/master/src/target.ts
如有任何意见,我们将不胜感激!谢谢。
不幸的是,您基本上想要限制变量的类型,同时让编译器推断该变量的类型。不幸的是,这不可能直接实现。
实现所需行为的唯一方法是使用函数。函数可以具有泛型类型参数,这些类型参数对其施加了约束,但最终类型参数将从传入的实际对象文字中推断出来:
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
是一个函数 returns 一个函数(即柯里化函数),以便允许指定第一个参数和推断第二个参数,