将泛型类型限制为 Typescript 中的几个类之一

2023-12-22

在 Typescript 中,如何在编译时将泛型类型限制为多个类之一?例如,如何实现这个伪代码?

class VariablyTyped<T has one of types A or B or C> {

    method(hasOneType: T) {
        if T has type A:
            do something assuming type A
        if T has type B:
            do something assuming type B
        if T has type C:
            do something assuming type C
    }
}

此外,我希望能够将属性(或任何变量)分配给泛型类型选项之一的特定后代类型,而不是仅分配给给定类型之一。例如:

class VariablyTyped<T has one of types A or B or C> {

    descendentClassOfT: T

    method(hasOneType: T) {
        descendentClassOfT = hasOneType
    }
}

class D extends class C {
    methodUniqueToD() { }
}

const v = new VariablyTyped(new D())
v.descendentClassOfT.methodUniqueToD()

这个答案显然并不明显,因为我花了几个小时。在我看来,这个问题的某种形式已经被问过 https://stackoverflow.com/questions/17125764/can-you-specify-multiple-type-constraints-for-typescript-generics,但给出的解决方案甚至不适合我编译。前面的问题可能只在非常具体的情况下得到回答,因为赞成票的数量表明它正在解决某些人的问题。

我发布这个新问题是为了清楚地说明一般问题并跟进解决方案。


我为此花了几个小时的时间,但回想起来,解决方案似乎是显而易见的。首先,我提出解决方案,然后将其与以前的方法进行比较。 (在 Typescript 2.6.2 中测试。)

// WORKING SOLUTION: union of types with type checks

class MustBeThis {
    method1() { }
}

class OrThis {
    method2() { }
}

abstract class OrOfThisBaseType {
    method3a() { }
}

class ExtendsBaseType extends OrOfThisBaseType {
    method3b() { }
}

class GoodVariablyTyped<T extends MustBeThis | OrThis | OrOfThisBaseType> {
    extendsBaseType: T;

    constructor(hasOneType: T) {
        if (hasOneType instanceof MustBeThis) {
            hasOneType.method1();
        }
        else if (hasOneType instanceof OrThis) {
            hasOneType.method2();
        }
        // either type-check here (as implemented) or typecast (commented out)
        else if (hasOneType instanceof OrOfThisBaseType) {
            hasOneType.method3a();
            // (<OrOfThisBaseType>hasOneType).method3a();
            this.extendsBaseType = hasOneType;
        }
    }
}

该解决方案的以下检查编译得很好:

const g1 = new GoodVariablyTyped(new MustBeThis());
const g1t = new GoodVariablyTyped<MustBeThis>(new MustBeThis());
const g1e: MustBeThis = g1.extendsBaseType;
const g1te: MustBeThis = g1t.extendsBaseType;

const g2 = new GoodVariablyTyped(new OrThis());
const g2t = new GoodVariablyTyped<OrThis>(new OrThis());
const g2e: OrThis = g2.extendsBaseType;
const g2te: OrThis = g2t.extendsBaseType;

const g3 = new GoodVariablyTyped(new ExtendsBaseType());
const g3t = new GoodVariablyTyped<ExtendsBaseType>(new ExtendsBaseType());
const g3e: ExtendsBaseType = g3.extendsBaseType;
const g3te: ExtendsBaseType = g3t.extendsBaseType;

将上述方法与先前接受的答案 https://stackoverflow.com/a/38891526/650894将泛型声明为类选项的交集:

// NON-WORKING SOLUTION A: intersection of types

class BadVariablyTyped_A<T extends MustBeThis & OrThis & OrOfThisBaseType> {
    extendsBaseType: T;

    constructor(hasOneType: T) {
        if (hasOneType instanceof MustBeThis) {
            (<MustBeThis>hasOneType).method1();
        }
        // ERROR: The left-hand side of an 'instanceof' expression must be of type
        // 'any', an object type or a type parameter. (parameter) hasOneType: never
        else if (hasOneType instanceof OrThis) {
            (<OrThis>hasOneType).method2();
        }
        else {
            (<OrOfThisBaseType>hasOneType).method3a();
            this.extendsBaseType = hasOneType;
        }
    }
}

// ERROR: Property 'method2' is missing in type 'MustBeThis'.
const b1_A = new BadVariablyTyped_A(new MustBeThis());
// ERROR: Property 'method2' is missing in type 'MustBeThis'.
const b1t_A = new BadVariablyTyped_A<MustBeThis>(new MustBeThis());

// ERROR: Property 'method1' is missing in type 'OrThis'.
const b2_A = new BadVariablyTyped_A(new OrThis());
// ERROR: Property 'method1' is missing in type 'OrThis'.
const b2t_A = new BadVariablyTyped_A<OrThis>(new OrThis());

// ERROR: Property 'method1' is missing in type 'ExtendsBaseType'.
const b3_A = new BadVariablyTyped_A(new ExtendsBaseType());
// ERROR: Property 'method1' is missing in type 'ExtendsBaseType'.
const b3t_A = new BadVariablyTyped_A<ExtendsBaseType>(new ExtendsBaseType());

还将上述工作方法与另一个建议的解决方案 https://stackoverflow.com/a/17125788/650894其中泛型类型被限制为扩展实现所有类接口选项的接口。这里发生的错误表明它在逻辑上与先前的非工作解决方案相同。

// NON-WORKING SOLUTION B: multiply-extended interface

interface VariableType extends MustBeThis, OrThis, OrOfThisBaseType { }

class BadVariablyTyped_B<T extends VariableType> {
    extendsBaseType: T;

    constructor(hasOneType: T) {
        if (hasOneType instanceof MustBeThis) {
            (<MustBeThis>hasOneType).method1();
        }
        // ERROR: The left-hand side of an 'instanceof' expression must be of type
        // 'any', an object type or a type parameter. (parameter) hasOneType: never
        else if (hasOneType instanceof OrThis) {
            (<OrThis>hasOneType).method2();
        }
        else {
            (<OrOfThisBaseType>hasOneType).method3a();
            this.extendsBaseType = hasOneType;
        }
    }
}

// ERROR: Property 'method2' is missing in type 'MustBeThis'.
const b1_B = new BadVariablyTyped_B(new MustBeThis());
// ERROR: Property 'method2' is missing in type 'MustBeThis'.
const b1t_B = new BadVariablyTyped_B<MustBeThis>(new MustBeThis());

// ERROR: Property 'method1' is missing in type 'OrThis'.
const b2_B = new BadVariablyTyped_B(new OrThis());
// ERROR: Property 'method1' is missing in type 'OrThis'.
const b2t_B = new BadVariablyTyped_B<OrThis>(new OrThis());

// ERROR: Property 'method1' is missing in type 'ExtendsBaseType'.
const b3_B = new BadVariablyTyped_B(new ExtendsBaseType());
// ERROR: Property 'method1' is missing in type 'ExtendsBaseType'.
const bt_B = new BadVariablyTyped_B<ExtendsBaseType>(new ExtendsBaseType());

具有讽刺意味的是,我后来解决了我的应用程序特定问题,而不必限制通用类型。也许其他人应该吸取我的教训,首先尝试寻找另一种更好的方法来完成这项工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将泛型类型限制为 Typescript 中的几个类之一 的相关文章

随机推荐

  • transactions/spring 事务传播会解决这个并发问题吗?

    如果可以的话 我有几个关于 Spring 事务的问题 假设我有这个 DAO 类 public class MyDAO verifies if a certain record in DB contains True in a certain
  • 实施比较方法的规则

    像compareTo一样 必须是 自反 反对称和传递 有什么规则来实现compare方法吗 谢谢 From 比较器API http docs oracle com javase 6 docs api java util Comparator
  • 使用 VBA 删除 Excel 中的工作表

    我有一个可以生成许多工作簿的宏 我希望宏在运行开始时检查文件是否包含 2 个电子表格 如果存在则删除它们 我尝试的代码是 If Sheet Name ID Sheet Then Application DisplayAlerts False
  • 某些阿拉伯文本显示不正确,而其他阿拉伯文本显示正常?

    I m developing an app with Arabic text in it My phone supports Arabic so the text gets displayed correctly the weird pro
  • 如何在 Swift 中类型转换子类 UIViewController?

    我正在尝试测试一个子类UITableViewController快速与故事板 我能够获取对视图控制器的引用并记录它 但我无法将其类型转换为我尝试测试的类 因此我无法访问方法 属性等 获取我的班级实例的正确方法是什么 测试场景 import
  • MIPS 堆栈帧(和“addiu”指令混淆)

    我是 MIPS 的新手 正在尝试了解函数的反汇编 编辑 它动态链接到 lib ld uClib so 0 并使用一些常用的 libc 函数 所以我假设它是使用 uClibc 工具链用 C 编写的 因此应该具有调用过程和堆栈帧等 在函数开始时
  • Haskell 中无点函数的先决条件是什么

    我一直认为 pointfree 函数的先决条件是将函数参数放在定义的末尾 例如 This can be made pointfree quite easily let lengths x map length x let lengths m
  • 从 OncePerRequestFilter 访问 spring beans

    我想从 OncePerRequestFilter 类访问 spring 组件 但是当我访问服务时我得到空指针 我认为原因是配置 我认为由于配置原因 过滤器是在 Spring 调度程序 servlet 之前被调用的 有什么好的方法可以完成这个
  • 使用seaborn绘制密度图

    我正在尝试绘制每小时需求的密度图 data https i stack imgur com JeI1d png hr 表示不同的时间 cnt 表示需求 我知道如何制作密度图 例如 sns kdeplot bike hr 然而 这仅在不同时间
  • pyodbc 将 SQL Server DATE 字段作为字符串返回

    我正在使用 pyodbc 查询包含 DATE 类型列的 SQL Server 2008 数据库表 生成的数据行包含日期字符串 而不是 python datetime date 或 datetime datetime 实例 这似乎只是 DAT
  • JS Chrome 顶部.文档

    Chrome 中相当于 top document 的内容是什么 在 FF 和 IE8 中均有效 在 Chrome 中 top 是有效的 top length 返回 2 帧 正如它应该的那样 但 top document 返回 未定义 需要获
  • QWebEngineView 在渲染之前修改网页内容

    我对 QWebengineView Qt 5 7 0 有三个问题 如何在加载期间 渲染之前 修改网页内容 添加额外的 html javascript 当网页中包含的javascript资源正在加载时 如何获取事件 我也想修改它们 我通过 p
  • 使用 VBA 在 MS Word 中创建表格

    在 MS Word 中创建表格的代码是什么 我已经使用宏的记录函数来查看它是如何编写的 但我不知道如何解释它 录制宏时不能画表格吗 绘制表格 功能呈灰色 我需要制作一个表格 其中包含一些合并的单元格 如果我可以绘制表格并使用宏进行记录会更容
  • 如何在 Visual C++ 控制台应用程序中捕获 Control-C 异常?

    这看起来应该很简单 但我已经尝试过 try catch C 异常处理和 try finally 结构化异常处理 SEH 并且两者都不会捕获当您 Control C 应用程序时发生的异常 我并没有真正期望 C 异常处理能够做到这一点 因为 C
  • 为什么 PHP 函数 htmlentities(...) 返回错误结果?

    我有以下代码 function testAccents str html htmlentities str echo html 当我运行它时 而不是得到 agrave eacute egrave I get Atilde nbsp Atil
  • 如何在基于 d3 力的布局中为节点标签内的文本添加下划线?

    我正在使用基于 d3 力的图形 其节点标签实际上是 URL 单击该 URL 时 会将用户带到目标 URL 出于可用性原因 有没有办法在网址下划线 更好的是 当用户将鼠标悬停在某个标签上时 下划线是否可以出现和消失 文本的颜色是否可以更改 这
  • 将列表转换为动态下拉列表时无法读取未定义的属性“映射”

    我正在努力将项目列表转换为动态下拉选项列表 但我遇到了问题 我检查了道具是否正确 确实如此 这是转换列表的代码片段 buildSelectOptions opts gt return opts map opt gt
  • 自定义 UITableViewCell 子视图布局

    我正在创建一个自定义UITableViewCell 风格类似UITableViewCellStyleValue1但右侧有一个可编辑的文本字段 而不是detailTextLabel 我对如何正确调整编辑字段的大小有点困惑 我想取的长度text
  • 通过 WCF 流式传输不确定数量的对象

    我有一个 WCF 服务 需要从数据库读取大量 10 到 2000 万 对象 我想做的是让客户端打开一个流 并让服务器在读取时从数据库推送数据 因此 客户端可以坐在循环中反序列化消息 直到从服务器获取 EOF 消息 采用 Twitter St
  • 将泛型类型限制为 Typescript 中的几个类之一

    在 Typescript 中 如何在编译时将泛型类型限制为多个类之一 例如 如何实现这个伪代码 class VariablyTyped