【发布时间】:2019-03-14 04:02:16
【问题描述】:
一些上下文:使用 graphql 我已经为自动生成的查询预定义了接口,但是任何给定查询的结果只是该自动生成接口的一个子集
为了对查询结果接口进行编译时检查,我需要一个接口,它是超级接口的自定义子集(严格没有任何附加参数),
一个例子……
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
interface IAutogenerated {
name : string
weight: number
age: number
}
interface ICustom extends RecursivePartial<IAutogenerated> {
name: string
agez : number // <------ I want this not allowed at compiletime ( ie: because it's a typo!)
}
let a : ICustom = {
name : "me" // this is required, weight is not because the usage of "RecursivePartial"
}
在这个例子中,我希望 ICustom 完全是 IAutogenerated 的一个子集(也许有一些“keyof”的创造性用法?
在 java 中,我会在扩展接口的每个成员中使用覆盖,以确保不添加错字并让编译器在重构期间帮助我..
打字稿版本:3.3
谢谢你, 弗朗切斯科
编辑: 鉴于汤姆的回答,我添加了另一个附加示例,这可能会进一步揭示 RecursivePartial 的实际用法
// ------ AUTOGENERATED INTERFACE OF GRAPHQL -----
export interface People {
id: number;
name: string;
gender: Gender;
age: number;
childs: (Maybe<People>)[];
}
/// CUSTOMIZATION BASED ON SINGLE CREATED QUERY
export type Child = Pick<RecursivePartial<People>,
'name'
>
export type PeopleListItem = Pick<RecursivePartial<People>,
'id'|'name'|'childs' >
// what is needed here something between the Pick ( which allow strict subset ) and RecursivePartial, which allow super-typing of subset elements )
// export interface PeopleListItem extends RecursivePartial<People>{
// id : number,
// name : string,
// childs : Child[] // NOTE --> here Child is a subtype of People
// }
给出一些上下文,这将构成 gql 的返回类型:
query {
people {
id
name
childs {
name
}
}
这里的注释代码我没有 Pick 的子类型严格性, 但我可以用 Pick 覆盖带有“Partial”的成员我不能覆盖元素但我有子类型严格性..
似乎是一个奇怪的问题,但这些约束都需要有一个类型化的对象子图
编辑 2: 我创建了一个提供一些要求的怪物,但它非常丑陋,我从 1 周开始就使用打字稿,所以请原谅我下面的代码..(请帮助我找到更好的东西)
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
type RecursivePartialPick<T, K extends keyof T> = {
[P in K]: RecursivePartial<T[P]>;
};
// ------ AUTOGENERATED INTERFACE OF GRAPHQL -----
export interface People {
id: number;
name: string;
gender: Gender;
age: number;
childs: (Maybe<People>)[];
}
/// CUSTOMIZATION BASED ON SINGLE CREATED QUERY
export type Child = RecursivePartialPick<People, 'name' >
// this will stabilize sub-fields Picke'd from the original type (Avoid typing errors and code duplication )
type _PeoplePick = 'id' | 'name' | 'childs';
// override the field with a subtype
interface _PeopleListItem extends RecursivePartialPick<People,_PeoplePick >{
childs : Child[] //<<--- note here : no safety against typing errors in "childs" field name ( Except that resulting type is not Child[] but (Maybe<People>)[];
}
export type PeopleListItem = Pick<_PeopleListItem,_PeoplePick>
let result : PeopleListItem = {
name : "" ,
id : 2 ,
childs : [{ // <Child[]>
name : "n"
}]
}
【问题讨论】:
-
我想补充一点,这对我来说不再是问题,我还没有找到这个“受限子类型定义”的解决方案,但是对于 graphql 查询,我现在正在生成专用(新)使用该库中的“typescript-client”插件为每个查询类型图(非子类型):
https://graphql-code-generator.com/docs/plugins/
标签: typescript typescript-typings