gpt4 book ai didi

typescript - TypeScript 中带有泛型的条件类型

转载 作者:行者123 更新时间:2023-12-04 12:59:08 24 4
gpt4 key购买 nike

我想实现的最好用代码来解释:

给定鞋类和服装类:

class Shoe {
constructor(public size: number){}
}
class Dress {
constructor(public style: string){}
}

有一个只能装鞋子或衣服的通用盒子。不能同时包含:
class Box <T extends Shoe | Dress > {
}

然后有一个实用程序类来处理移动鞋子:
class ShoeMover {
constructor(public size: number[]){}
}

此外,用于移动连衣裙的实用程序类:
class DressPacker {
constructor(public style: string[]){}
}

然后有一个通用的移动器,如果用 Box<Shoe> 实例化或 Box<Dress>有一个 mover使用 ShoeMover 的方法或 DressPacker :
class Move<B extends Box<Shoe> | Box<Dress>> {
private box: B;
constructor(toMove: B) {
this.box = toMove;
}
public mover(tool: ShoeMover | DressPacker) {
}
}

那么编译时间保证应该是,如果 MoveBox<Shoe> 实例化,然后是 mover方法应该只接受 ShoeMover .如果用 Box<Dress> 实例化. mover方法应该只接受 DressPacker .那是:
let shoemover = new Move(new Box<Shoe>());

// compile
shoemover.mover(new ShoeMover([21]))

// should not compile. But currently does
shoemover.mover(new DressPacker(["1"]))

我尝试使用条件类型,但我想涉及泛型的事实使预期的解决方案不起作用。基本上这是我尝试过的:
type MoverFromEitherShoeOrDressA<T> =
T extends Box<infer U> ?
U extends Shoe ? ShoeMover :
U extends Dress ? DressPacker :
never:
never;

and

type MoverFromEitherShoeOrDressB<T> =
T extends Box<Shoe> ? ShoeMover:
T extends Box<Dress> ? DressPacker:
never;

然后改变 mover的定义从:
public mover(tool: ShoeMover | DressPacker) {
}


public mover(tool: MoverFromEitherShoeOrDressB) {
}

or

public mover(tool: MoverFromEitherShoeOrDressA) {
}

..但是这些并没有提供我所寻求的编译时间保证。

有谁知道如何实现这一目标?

编辑。

接受的答案适用于上述场景。但是有一个稍微不同的场景不起作用。我决定更新,而不是创建另一个问题。场景是当 Move 的构造函数时更改为采用联合类型。
type Mover<T> = 
T extends Shoe ? ShoeMover :
T extends Dress ? DressPacker :
never;

class Move<T extends Shoe | Dress> {
private box: Box<T>;
constructor(public toMove: Box<Shoe>[] | Box<Dress>[]) {
this.box = toMove;
}
public mover(tool: Mover<T>) {
}
}


let shoemover = new Move(new Array<Box<Shoe>>());

// compile
shoemover.mover(new ShoeMover([21]))

// should not compile. But currently does
shoemover.mover(new DressPacker(["1"]))

Playground Link

最佳答案

你快到了,你只需要在 mover 中使用泛型方法也一样,否则它不知道是什么T伊斯兰国。将泛型类型视为以泛型 T 作为参数的方法,以及 <>() :

type Mover<T> = 
T extends Shoe ? ShoeMover :
T extends Dress ? DressPacker :
never;

class Move<T extends Shoe | Dress> {
private box: Box<T>;
constructor(toMove: Box<T>) {
this.box = toMove;
}
public mover(tool: Mover<T>) {
}
}

此外,我更改了 Move定义排除 Box泛型,因为您可以轻松地将其封装在类内部定义中,但您的解决方案也适用于:
type MoverFromEitherShoeOrDressA<T> =
T extends Box<infer U> ?
U extends Shoe ? ShoeMover :
U extends Dress ? DressPacker :
never:
never;

public mover(tool: MoverFromEitherShoeOrDressA<B>) { // <-- Here
}


编辑:在此处添加游乐场: Playground Link

关于typescript - TypeScript 中带有泛型的条件类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61541059/

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