简体   繁体   English

在 TS 上使用其他类型中的类型名称

[英]Use name of type in other types on TS

I have types:我有类型:

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",
}

base on this types, how i can create type something like that (the part of the Type below is pseudocode):基于这种类型,我如何创建类似的类型(下面的类型部分是伪代码):

type TResponse<T> = {
   data: T extends TUser ? TUser[] : {[TDataMethod[T]]: T}
   time: string,
}

for objects对于对象

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"
}

or i have one way - use extends declaration?或者我有一种方法 - 使用扩展声明?

It is possible with some Typescript "programming".一些 Typescript “编程”是可能的。

For example, I have these interfaces.例如,我有这些接口。

interface User {
  name: string;
  age: number;
}

interface Bot {
  name: string;
  author: string;
}

The Metadata should be an array so we could iterate from it. Metadata应该是一个数组,以便我们可以从中迭代。

type Metadata = [
  {
    name: 'users';  // here's the property
    type: User;     // here's the type
  },
  {
    name: 'bots';
    type: Bot;
  }
];

We don't actually could iterate from it.我们实际上不能从中迭代。 So, create an helper named ArrayUnshift which will unshift (remove first item) from the generic type.因此,创建一个名为ArrayUnshift的助手,它将从泛型类型中取消移位(删除第一项)。 If the generic type ( Array ) is [first, ...rest] , then return the rest so the first item is removed.如果通用类型 ( Array ) 是[first, ...rest] ,则返回 rest 以便删除第一项。

type ArrayUnshift<Array extends any[]> = 
  Array extends [infer First, ...infer Rest] ?
    Rest : never;

Then we could itearate the Metadata .然后我们可以迭代Metadata If the first Metadata.type is equal to generic type, then return the Metadata.name , if not recursive to itself but unshift the 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>>;

Last, create ResponseData with MetadataProperty<T> as its property.最后,使用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
  }
}

There's a repo that related to this topic, take a look to Type Challenges .有一个与此主题相关的回购协议,请查看Type Challenges


EDIT: Or you could simply use Extract utility as being said by @caTS .编辑:或者您可以简单地使用@caTS所说的 Extract 实用程序。

You don't need to "iterate" over them;您不需要“迭代”它们; just get the elements as a union and use Extract: Extract<Metadata[number], { type: T }>["name"] .只需将元素作为联合获取并使用 Extract: Extract<Metadata[number], { type: T }>["name"]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM