gpt4 book ai didi

typescript - 在 typescript 中将一种类型映射到另一种类型

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

我正在尝试通过泛型将一个类类型映射/匹配到另一个类型。举个例子会更清楚:

class BaseClass {
//...
public someGenericClassStuff: 'someGenericClassStuff' = 'someGenericClassStuff';
}
class BaseProps {
//...
public someGenericStuff: 'someGenericStuff' = 'someGenericStuff';
}


class FooClass extends BaseClass {
//...
public someFooClassStuff: 'someFooClassStuff' = 'someFooClassStuff';
}
class FooProps extends BaseProps {
public someFooSpecificStuff: 'someFooSpecificStuff' = 'someFooSpecificStuff';
//...
}


class BarClass extends BaseClass{
//...
public someBarClassStuff: 'someBarClassStuff' = 'someBarClassStuff';
}
class BarProps extends BaseProps {
public someBarSpecificStuff: 'someBarSpecificStuff' = 'someBarSpecificStuff';
//...
}


type AllClass = BarClass | FooClass;
type AllProps = BarProps | FooProps;

type SpecificProps<T extends AllClass> = // Wondering what goes here

const test: SpecificProps<BarClass> = new BarProps(); // Works
const test2: SpecificProps<FooClass> = new FooProps(); // Works
const test3: SpecificProps<BarClass> = new FooProps(); // Fails

我尝试了几个选项,这是最接近我的选项:

type SpecificProps<T extends AllClass> = 
T extends BarClass ? BarProps :
T extends FooClass ? FooProps :
never;

这个解决方案在我上面的例子中工作得很好,但是当我开始添加越来越多的类和它们之间的联合时,它开始崩溃,有时会返回错误的类型。此外,编写起来也不是最方便的,因为我有 2 个以上的类,每次添加一个类时,我也需要扩充这种类型。

我理想的解决方案是做类似的事情

class BarClass extends BaseClass {
//...
public someBarClassStuff: 'someBarClassStuff' = 'someBarClassStuff';

type props = BarProps;
}

// And my type would become
type SpecificProps<T extends AllClass> = T['props'];

但我知道这在 typescript 中不存在。我将不得不创建一个实际变量而不是类型,并且除了类型匹配之外,它会占用内存。

Here's a TS Playground of the above example

最佳答案

你要找的是类似 "type families" 的东西对于 TypeScript,您可以在其中将类型与其他类型相关联,而不必下降到值级别并创建(或假装创建)不必要的运行时属性来这样做。在 microsoft/TypeScript#17588 处有一个开放的 GitHub 请求要求这样做,但我看不到那里有太多动静。


您已经有了一个涉及构建您自己的条件类型的解决方法;可能对此进行了一些调整,这可能对您的边缘情况表现得更好,但没有 minimal, reproducible example对于这种极端情况,我不会费心去尝试走那条路。


相反,让我们看看与您所需的类型系列解决方案类似的解决方法。我们在每个 XXXClass 类中创建一个“幻影”属性值,它在运行时实际上并不存在,尽管您声称它存在:

class BaseClass {
public someGenericClassStuff: 'someGenericClassStuff' = 'someGenericClassStuff';
declare __phantomPropsType: BaseProps;
}

我在这里使用 declare property modifier .它对运行时没有影响,但现在 TypeScript 认为每个 BaseClass 都有一个名为 __phantomPropsType 的属性。如果你愿意,你可以眯着眼睛阅读它作为 type propsType = BaseProps。这是其余的:

class FooClass extends BaseClass {
public someFooClassStuff: 'someFooClassStuff' = 'someFooClassStuff';
declare __phantomPropsType: FooProps;
}

class BarClass extends BaseClass {
public someBarClassStuff: 'someBarClassStuff' = 'someBarClassStuff';
declare __phantomPropsType: BarProps;
}

现在您的 SpecificProps 通过简单的查找就脱离了它,并且不需要构建一个名为 AllClass 的联合:

type SpecificProps<T extends BaseClass> = T['__phantomPropsType']

这与您的示例相同:

const test: SpecificProps<BarClass> = new BarProps(); // Works
const test2: SpecificProps<FooClass> = new FooProps(); // Works
const test3: SpecificProps<BarClass> = new FooProps(); // Fails

这是一种解决方法,因为编译器确实认为存在此 __phantomPropsType 属性。双下划线有点暗示它是一个幻影属性(您往往会在品牌类型等其他用法中看到这一点),但它仍然会在 IntelliSense 等中“有用地”弹出:

const n = new FooClass();
n.__phantomPropsType // eh, not great

Playground link to code

关于typescript - 在 typescript 中将一种类型映射到另一种类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65707464/

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