我的问题与this非常相似,但我的问题有点棘手,因为我想保留空字段和可选字段。
假设我有一个运送页面的 GraphQL 查询,如下所示:
query getShippingData() {
myData {
address {
country {
twoDigitsCode
}
}
}
}
我有一个包含 GraphQL 端点生成的所有可能接口的生成文件:
interface GQLUserData {
id: string;
email?: null | string;
address?: null | GQLUserAddress;
}
interface GQLUserAddress {
street: string;
city: string;
state: string;
country?: null | GQLCountry;
}
interface GQLCountry {
id: string;
name: string;
available: boolean;
twoDigitsCode?: null | string;
}
但是我不能只导入和使用整个 GQLCountry,因为它包含我在查询中没有要求的其他几个属性。
如何使用生成的对我有利的类型文件来完成下面的界面?
interface ShippingDataResponse {
myData: {
address?: null | {
country?: null | {
twoDigitsCode?: null | string;
}
}
}
}
我链接的类似问题通过使用
Pick
类型实用程序并重新声明选取的字段和嵌套选取的接口来解决它。
interface ShippingDataResponse {
myData: {
address: {
country: Pick<GQLCountry, 'twoDigitsCode'>;
}
}
}
虽然这看起来完全符合我的要求,但这实际上是将
address
和 country
重新声明为非可选和不可空字段,并且会导致错误的接口,如下所示:
interface ShippingDataResponse {
myData: {
address: {
country: {
twoDigitsCode?: null | string;
}
}
}
}
这完全消除了
address
和 country
的可空性/可选性。
为了解决这个问题,我必须进入生成的类型文件,查看哪些字段是可选的或可为空的,并手动将它们标记为如此。
这首先使生成的类型文件的全部意义失效,因为它是 4K LOC 文件,并且可能会在没有任何事先通知的情况下发生更改。
我需要我的类型始终与 GraphQL 生成的值保持同步。
来自 ts-essentials 通过选择一组属性来构造一个类型,这些属性在类型
DeepPick<Type, Filter>
中具有来自类型
true
的属性值
Filter
。
Type
用法如下:
import { DeepPick } from 'ts-essentials';
type InitialShippingResponse = DeepPick<
{ myData: GQLUserData },
{
myData: {
address: {
country: {
twoDigitsCode: true
}
}
}
}
>;