[英]Is there a way to replace a generic type by another type inside an interface?
我有一个包含这些接口的文件:
export type Flatten<T> = T extends any[] ? T[number] : T;
export interface IGeneric<T> {
data: T extends any[] ? T : Flatten<T> | null;
meta: IGenericMeta;
}
export type IGenericData<T> = Pick<IGeneric<T>, 'data'>;
export interface IGenericMeta {
pagination?: {
page: number;
pageSize: number;
pageCount: number;
total: number;
};
}
// I use it like that :
interface ITest {
id: number;
attributes: {
field1: string;
relation1: IGenericData<ITest2>;
}
}
interface ITest2 {
id: number;
attributes: {
field1: string;
}
}
当我检索数据时一切都很好,但是对于插入我不能再使用它了,我需要将字段relation1
设置为number | null
number | null
。
如果我这样设置关系:
// ...
interface ITest {
id: number;
attributes: {
field1: string;
relation1: IGeneric<ITest2> | number | null;
}
}
const test: IGeneric<ITest> = {
meta: {},
data: {
id: 1,
attributes: {
field1: '',
relation1: {
data: {
id: 2,
attributes: {
field1: 'test',
},
},
},
},
},
};
↓ error here
if (test.data?.attributes?.relation1?.data?.id) {
}
Typescript 对我大喊:
Property 'data' does not exist on type 'number | IGenericData<ITest2>'.
Property 'data' does not exist on type 'number'.ts(2339)
我可以设置两个接口来扩展基础接口,如下所示:
interface ITestBase {
id: number;
attributes: {
field1: string;
}
}
type ITestInsert = ITestBase & {
attributes: {
relation1: number | null;
}
}
interface ITestRetrieve = ITestBase & {
attributes: {
relation1: IGeneric<ITest2>;
}
}
但我不太喜欢这种设置,因为我已经有很多接口,而且我不打算花整整一周的时间来重构这种方式。
我想找到一种使用泛型类型(也许?)的方法来覆盖我之前设置的行为,以将所有 IGenericData 替换为number | null
number | null
type Replace<T> = ???
type Test = Replace<ITest['attributes']>;
也许这个问题已经得到回答,但我没有找到任何与我想做的事情相关的事情。 如果已经有答案,请提前道歉。
编辑1:
警告:这种深度类型转换通常有很多边缘情况,因此您应该针对您的用例彻底测试任何建议的解决方案,并准备根据结果修改或放弃它。 我将根据您问题中的示例进行回答。
看起来您希望Replace<T>
成为递归条件类型; 如果T
是一些GenericData
,那么您将用number | null
替换它 number | null
。 如果T
是原始类型,您希望不理会它。 否则,如果T
是某个 object 类型,您希望向下递归到它和map每个属性到该属性的Replace
d 版本。
该方法转化为以下代码:
type Replace<T> = T extends IGenericData<any> ? (number | null) :
T extends object ? { [K in keyof T]: Replace<T[K]> } : T;
让我们看看它是否有效:
type ReplacedITestAttributes = Replace<ITestAttributes>;
/* type ReplacedITestAttributes = {
field1: string;
relation1: number | null;
} */
type ReplacedITest = Replace<ITest>;
/* type ReplacedITest = {
id: number;
attributes: {
field1: string;
relation1: number | null;
};
} */
看起来不错
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.