简体   繁体   English

如何在 TypeScript 中制作不同泛型的类型级列表?

[英]How do I make a type-level list of varying Generics in TypeScript?

Given this type:鉴于这种类型:

type AThingWithGenerics<A, B, C> = {
  name: string;
  someFunction: (id: number) => A;
  anotherFunction: () => B;
  loveSomeGenerics: (s: string) => { foo: C };
};

Where A , B , and C are objects that vary across values.其中ABC是随值变化的对象。 For example:例如:

const aThing: AThingWithGenerics<{ foo: string }, { foo: number, bar: string }, { bar: string }> = {
  name: "a_thing",
  someFunction: (id: number) => { return { foo: "bar" }; },
  anotherFunction: () => { return { foo: 3, bar: "foo" } },
  loveSomeGenerics: (s: string) => { return { foo: { bar: "In this case C is an object containing a string" + s } }; },
}

const anotherThing: AThingWithGenerics<{ bar: number }, { aString: string }, { bar: "test" }> = {
  name: "another_thing",
  someFunction: (id: number) => { return { bar: id + 1 }; },
  anotherFunction: () => { return { aString: "test" } },
  loveSomeGenerics: (s: string) => { return { foo: { bar: "test" } } },
}

It's possible to create a tuple of specific AThingWithGenerics :可以创建特定AThingWithGenerics的元组:

type ASpecificPileOfThings = [typeof aThing, typeof anotherThing];

It's also possible to make a list of AThingWithGenerics as long as A , B , and C do not vary:只要ABC不变化,也可以制作AThingWithGenerics列表:

type APileOfTheSameThing<A, B, C> = [AThingWithGenerics<A, B, C>];

But I am trying to add a list of related AThingWithGenerics to AThingWithGenerics , so aThing might include [anotherThing] as its related .但我正在尝试将相关AThingWithGenerics列表添加到AThingWithGenerics ,因此aThing可能包含[anotherThing]作为其related . The problem is A , B , and C in related will vary.问题是ABCrelated会有所不同。

So how do I create a type that contains varying generics?那么如何创建一个包含不同泛型的类型呢? This is what I have so far:这是我到目前为止:

type AThingWithGenericsII<A, B, C> = {
  name: string;
  someFunction: (id: number) => A;
  anotherFunction: () => B;
  loveSomeGenerics: (s: string) => { foo: C };
  related: [AThingWithGenericsII<A,B,C>]
}

const aThingWithRelated: AThingWithGenericsII<{foo: string, bar: string }, { property: string }, { nestedFoo: number }> = {
  name: "a_thing_with_related",
  someFunction: (id: number) => { return { foo: "This is a string", bar: "" } },
  anotherFunction: () => { return { property: "bar" } },
  loveSomeGenerics: (s: string) => { return { foo: { nestedFoo: 3.1 } } },
  related: [aThing, anotherThing]
}

This does not typecheck, since A , B , and C s types do not unify.这不会进行类型检查,因为ABC的类型不统一。 How can AThingWithGenericsII be changed so aThingWithRelated type checks?如何AThingWithGenericsII被改变,以aThingWithRelated类型检查?

TypeScript playground link . 打字稿游乐场链接 I'm sure this question about recursive Generics is related, but I couldn't get it to work for my case.我确定这个关于递归泛型的问题是相关的,但我无法让它适用于我的案例。

Try using the first interface AThingWithGenerics you have defined but with this added in, you do not need the others :尝试使用您定义的第一个接口AThingWithGenerics ,但是添加了这个接口,您不需要其他接口:

type AThingWithGenerics<A = any, B = any, C = any> = {
  name: string;
  someFunction: (id: number) => A;
  anotherFunction: () => B;
  loveSomeGenerics: (s: string) => { foo: C };

  // some things might not have relatives
  related?: Array<AThingWithGenerics>
};

Using type any with the generic definitions will make typescript infer the types of generics used in a specific instance.将 type any与泛型定义一起使用将使 typescript 推断特定实例中使用的泛型类型。 We do this to allow the related property to use any generics that will ultimately be inferred by typescript.我们这样做是为了允许related属性使用最终将由打字稿推断的任何泛型。

Just to add the sentiment behind the interface, I figured not all "things" will be related so that is why it is possibly undefined , which was the initial ts error found on the link you provided.只是为了添加界面背后的情绪,我认为并非所有“事物”都会相关,这就是为什么它可能是undefined ,这是在您提供的链接上发现的初始ts错误。

Playgound 游乐场

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

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