gpt4 book ai didi

Typescript - 扩展自身的通用类型

转载 作者:搜寻专家 更新时间:2023-10-30 20:55:15 25 4
gpt4 key购买 nike

我最近遇到了一些看起来像这样的东西:

interface Test<T extends Test<T>> {
a: number;
b: T;
}

function foo <T extends Test<T>>(el: T): T {
...
}

我不得不说我对这究竟是什么以及为什么需要这样的东西感到有点困惑。我经历过 Generics section Typescript 手册,但找不到类似的内容。

该接口(interface)实现了哪些无法通过以下方式实现的功能?

interface Test<T>

任何人都可以阐明这一点吗?

最佳答案

没有实际例子,只能泛泛而谈。在像 Java 这样没有 polymorphic this types 的语言中,您需要这种语法。 ,我很快就会谈到。


我们的想法是,您需要一个泛型类型,它引用与其包含的类或接口(interface)相同类型的其他对象。让我们看看你的Test接口(interface):

interface Test<T extends Test<T>> {
a: number;
b: T;
}

这描述了一个类似链表的结构,其中 b Test<T> 的属性也必须是 Test<T> , 自 T延伸Test<T> .但另外,它必须是与父对象相同类型(的子类型)。下面是两个实现的示例:

interface ChocolateTest extends Test<ChocolateTest> {
flavor: "chocolate";
}
const choc = {a: 0, b: {a: 1, flavor: "chocolate"}, flavor: "chocolate"} as ChocolateTest;
choc.b.b = choc;

interface VanillaTest extends Test<VanillaTest> {
flavor: "vanilla";
}
const vani = {a: 0, b: {a: 1, flavor: "vanilla"}, flavor: "vanilla"} as VanillaTest;
vani.b.b = vani;

两者都是 ChocolateTestVanillaTestTest 的实现, 但它们不可互换。 b ChocolateTest 的属性是 ChocolateTest , 而 b VanillaTest 的属性是 VanillaTest .所以出现如下错误,这是可取的:

choc.b = vani; // error!

现在您知道什么时候拥有 ChocolateTest整个列表充满了其他 ChocolateTest无需担心其他一些实例 Test出现:

choc.b.b.b.b.b.b.b.b.b // <-- still a ChocolateTest

将此行为与以下界面进行比较:

interface RelaxedTest {
a: number;
b: RelaxedTest;
}

interface RelaxedChocolateTest extends RelaxedTest {
flavor: "chocolate";
}
const relaxedChoc: RelaxedChocolateTest = choc;

interface RelaxedVanillaTest extends RelaxedTest {
flavor: "vanilla";
}
const relaxedVani: RelaxedVanillaTest = vani;

你可以看到RelaxedTest不限制 b属性与父级相同类型,仅用于 RelaxedTest 的某些实现.到目前为止,它看起来是一样的,但下面的行为是不同的:

relaxedChoc.b = relaxedVani; // no error

这是允许的,因为 relaxedChoc.b类型为 RelaxedTest ,这relaxedVani兼容。鉴于 choc.b类型为 Test<ChocolateTest> ,这vani 兼容。


一种类型将另一种类型限制为与原始类型相同的能力很有用。它非常有用,事实上,TypeScript 有一个叫做 polymorphic this 的东西。就是为了这个目的。您可以使用 this作为一种类型表示“与包含的类/接口(interface)相同的类型”,并取消上面的通用内容:

interface BetterTest {
a: number;
b: this; // <-- same as the implementing subtype
}

interface BetterChocolateTest extends BetterTest {
flavor: "chocolate";
}
const betterChoc: BetterChocolateTest = choc;

interface BetterVanillaTest extends BetterTest {
flavor: "vanilla";
}
const betterVani: BetterVanillaTest = vani;

betterChoc.b = betterVani; // error!

这与原始 Test<T extends Test<T>> 几乎相同没有 possibly mind-bending circularity .所以,是的,我建议使用多态 this相反,除非您有一些令人信服的理由以其他方式进行。

既然你说你遇到过这段代码,我想知道它是否是引入多态之前的一些代码 this ,或者不知道的人,或者是否有一些我不知道的令人信服的理由。不确定。


希望这对您有所帮助。祝你好运!

关于Typescript - 扩展自身的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50276476/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com