[英]Use name of type in other types on TS
我有类型:
type TUser= {
id: number,
name: string,
}
type TFields = {
value: number,
name: string,
otherField: string,
}
type TTask = {
id: number,
title: string,
}
type TDataMethod = {
"TField": "fields",
"TTask": "tasks",
}
基于这种类型,我如何创建类似的类型(下面的类型部分是伪代码):
type TResponse<T> = {
data: T extends TUser ? TUser[] : {[TDataMethod[T]]: T}
time: string,
}
对于对象
const userResponse: TResponse<TUser> = {
data: [
id: 1,
name: "John",
],
time: "13 august 2022"
}
const taskResponse: TResponse<TTask> = {
data: {
tasks: {
id: 1,
title: "Some task",
}
},
time: "14 august 2022"
}
或者我有一种方法 - 使用扩展声明?
一些 Typescript “编程”是可能的。
例如,我有这些接口。
interface User {
name: string;
age: number;
}
interface Bot {
name: string;
author: string;
}
Metadata
应该是一个数组,以便我们可以从中迭代。
type Metadata = [
{
name: 'users'; // here's the property
type: User; // here's the type
},
{
name: 'bots';
type: Bot;
}
];
我们实际上不能从中迭代。 因此,创建一个名为ArrayUnshift
的助手,它将从泛型类型中取消移位(删除第一项)。 如果通用类型 ( Array
) 是[first, ...rest]
,则返回 rest 以便删除第一项。
type ArrayUnshift<Array extends any[]> =
Array extends [infer First, ...infer Rest] ?
Rest : never;
然后我们可以迭代Metadata
。 如果第一个Metadata.type
等于泛型类型,则返回Metadata.name
,如果不是递归到自身但取消移动Metadata
。
type MetadataProperty<T extends any, Data extends any[] = Metadata> =
Data[0]['type'] extends T ?
Data[0]['name'] : MetadataProperty<T, ArrayUnshift<Data>>;
最后,使用MetadataProperty<T>
作为其属性创建ResponseData
。
interface ResponseData<T extends object> {
time: string;
data: MetadataProperty<T> extends string ? {
[Key in MetadataProperty<T>]: T;
} : {
string: T; // fallback to avoid error
}
}
有一个与此主题相关的回购协议,请查看Type Challenges 。
编辑:或者您可以简单地使用@caTS所说的 Extract 实用程序。
您不需要“迭代”它们; 只需将元素作为联合获取并使用 Extract:
Extract<Metadata[number], { type: T }>["name"]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.