嵌套打字稿泛型 [英] Nested Typescript Generics

查看:83
本文介绍了嵌套打字稿泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

class Walls { }
class Furniture { }
class Layout<T extends Walls | Furniture> { }
class Space extends Layout<Walls> { }
class Room extends Layout<Furniture> { }

我需要创建这两个类:

class SpaceController extends LayoutController<Space> { }
class RoomController extends LayoutController<Room> {}

为此,我不能创建这样的LayoutController类:

To do this, I can't create LayoutController class like this:

class LayoutController<T extends Layout>{ }

因为Layout需要一个Type参数.

because Layout needs a Type parameter.

我可以改成这个:

class LayoutController<U, T extends Layout<U extends Walls | Furniture>>{ }

但这意味着我将必须这样做:

but that would mean I will have to do this:

class SpaceController extends LayoutController<Walls, Space> { }
class RoomController extends LayoutController<Furniture, Room> {}

我觉得这是多余的.此外,它还为出错提供了空间.没有什么可以阻止我写作:

which I feel is redundant. Moreover, it opens up room for errors. There's nothing stopping me from writing:

class RoomController extends LayoutController<Walls, Room> {}

我该如何解决?

有关LayoutController的更多详细信息:

class LayoutController<T> extends React.Component<{}, LayoutControllerState<T>>() { }
interface LayoutControllerState<T> { 
  selectedLayout: T;
}

推荐答案

虽然多键入两种类型的参数的解决方案还不错,但是如果U与预期的T不兼容,则会给您适当的错误.布局,如果正确指定了类型约束:

While a bit more typing a two type parameter solution is not bad and will give you appropriate errors if U is not compatible with the T expected by layout, if type constraints are properly specified:

class Walls { height!: number; }
class Furniture { price!: number; }
class Layout<T extends Walls | Furniture> { children: T[] = []; }
class Space extends Layout<Walls> { private x: undefined; }
class Room extends Layout<Furniture> { private x: undefined; }

class LayoutController<U extends Walls | Furniture, T extends Layout<U>>{
    getValue(u: U) : void{}
}

class SpaceController extends LayoutController<Walls, Space> { }
class RoomController extends LayoutController<Furniture, Room> {}
class ErrController extends LayoutController<Walls, Room> {}  //Type 'Room' does not satisfy the constraint 'Layout<Walls>

我们可以使用条件类型从Layout类型中提取通用参数,并将其作为U的默认值提供.因此,我们不必指定冗余参数:

We can use a conditional type to extract the generic parameter from the Layout type and provide this as default for U. Thus we don't have to specify the redundant parameter:

type ExtractLayoutParameter<T extends Layout<any>> = T extends Layout<infer U> ? U: never;
class LayoutController<T extends Layout<any>, U extends Walls | Furniture= ExtractLayoutParameter<T>>{
    getValue(u: U) : void{}
}

class SpaceController extends LayoutController<Space> { }
class RoomController extends LayoutController<Room> {}
new SpaceController().getValue(new Walls())
new SpaceController().getValue(new Furniture()) // error

我们也可以使用条件类型而不是U,从而不允许用户将U更改为布局所接受的派生类型(取决于您的用例,取决于您决定的功能或设计限制) :

We could also use the conditional type instead of U thus not allowing the user to change U to a derived type of that accepted by the layout (depeding on your use case a feature or a design limitation you decide):

type ExtractLayoutParameter<T extends Layout<any>> = T extends Layout<infer U> ? U: never;
class LayoutController<T extends Layout<any>>{
    getValue(u: ExtractLayoutParameter<T>) : void{}
}

class SpaceController extends LayoutController<Space> { }
class RoomController extends LayoutController<Room> {}
new SpaceController().getValue(new Walls())
new SpaceController().getValue(new Furniture()) // error

这篇关于嵌套打字稿泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆