TypeScript 提供(未指定)泛型类型作为泛型参数

2024-05-22

我希望提供一个泛型类型作为类型参数无需先将其解析为具体类型。换句话说,我正在寻找一种方法来指定从基类继承时可以使用的类型映射函数。

示例(不正确的)语法希望比我能解释得更好:

abstract class RunIt<SomeMagicConverter> {
    // The return type for this function depends on the type of the
    // argument *and* on the way the implementation class was declared:
    run<T>(o: T): SomeMagicConverter<T> { // (syntax error)
        return this.handle(o); // (imagine this does something more interesting)
    }
    protected abstract handle<T>(o: T): SomeMagicConverter<T>; // (syntax error)
}

type MyMagicConverter<T> = TypeIWantToReturn<T>; // MyMagicConverter is generic
class MyRunIt extends RunIt<MyMagicConverter> { // but we don't specify T here
    // [...]
}
new MyRunIt().run(7); // call infers T is number, so returns TypeIWantToReturn<number>
new MyRunIt().run(''); // now T is string, so returns TypeIWantToReturn<string>

此外,我想限制这一点,以便SomeMagicConverter<T> extends SomeBase<T>是有保证的。 IE。

abstract class RunIt<SomeMagicConverter extends SomeBase>

对于我希望如何使用它的更具体的示例,这是一个带有缓存的包装的基本基类(不完全是我的实际用例,但演示了需要):

interface Wrapped<T> {
    contains(other: T): boolean;
}

abstract class Store {
    private readonly cached = new Map<any, any>();

    protected abstract applyWrap<T>(o: T): Wrapped<T>;

    wrap<T>(o: T): Wrapped<T> { // <-- this should return something more specific
        if (!this.cached.has(o)) {
            this.cached.set(o, this.applyWrap(o));
        }
        return this.cached.get(o);
    }
}

class Foo<T> implements Wrapped<T> {
    constructor(private readonly o: T) {}
    contains(other: T): boolean { return other === this.o; }
    extraFooFunc(): void {}
}

class FooWrapper extends Store {
    constructor() { super(); }
    protected applyWrap<T>(o: T): Foo<T> { return new Foo<T>(o); }
}

new FooWrapper().wrap(4).extraFooFunc(); // syntax error because extraFooFunc is not defined on Wrapped

显然,我可以通过定义包装方法来解决这个问题,但我想避免在每个子类上都这样做:

class FooWrapper extends Store {
    // [...]
    wrap<T>(o: T): Foo<T> { return super.wrap(o) as Foo<T>; }
}

尚不支持通用泛型参数(2021 年 3 月)。看打字稿问题 https://github.com/Microsoft/TypeScript/issues/1213 and a 类似的问题 https://stackoverflow.com/questions/54037783了解更多信息。

但是,您所描述的可以使用来实现索引访问类型 https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html and 映射类型 https://www.typescriptlang.org/docs/handbook/2/mapped-types.html:

// Any Converter to be used with RunIt must be added to Converters
interface Converters<T> { }

// All Converters must implement this interface
interface ConverterBase<T> { length: number }

// Maps valid keys to themselves, invalid ones to `never`
type ValidKey<T, K extends keyof Converters<T>> =
    Converters<T>[K] extends ConverterBase<T> ? K : never;

// Contains all entries from Converters where the type extends ConverterBase
type ConstrainedConverters<T> = {
    [K in keyof Converters<T> as ValidKey<T, K>]: Converters<T>[K];
};

abstract class RunIt<K extends keyof ConstrainedConverters<void>> {
    run<T>(o: T): ConstrainedConverters<T>[K] {
        return this.handle(o);
    }
    protected abstract handle<T>(o: T): ConstrainedConverters<T>[K];
}

// Re-open Converters and add some Converters
interface Converters<T> { Id: T, Array: Array<T> }

class ArrayRunIt extends RunIt<'Array'> {
    protected handle<T>(o: T) { return [o]; }
}

// @ts-expect-error Type '"Id"' does not satisfy the constraint '"Array"'.(2344)
class IdRunIt extends RunIt<'Id'> {
    protected handle<T>(o: T) { return o; }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TypeScript 提供(未指定)泛型类型作为泛型参数 的相关文章

随机推荐

  • Android 上 WebRTC 的自定义视频源

    Overview 我想使用自定义视频源通过 WebRTC Android 实现来直播视频 如果我理解正确的话 现有的实现仅支持 Android 手机上的前置和后置摄像头 以下类与此场景相关 Camera1Enumerator java ht
  • 从字符串中提取电子邮件地址

    我有一个像这样的字符串 Francesco Renga lt email protected cdn cgi l email protection gt 我只需要提取电子邮件 即 电子邮件受保护 cdn cgi l email protec
  • 防止更新 ASP.NET MVC 和实体框架中未更改的值

    我正在使用 ASP NET MVC 和实体框架 我有一个 编辑人员 网页 可以在其中编辑人员的字段 然后在回发操作中 我使用以下代码 var person objectCtx Persons Where s gt s Id id First
  • “结构类型防护”与“if”配合使用,但不能用作数组过滤谓词

    我有一个联合类型 Pet在下面的示例中 组合了多个对象类型 每个对象类型都有一个type指示其类型的属性 有时我有一个联合类型的数组 Pet 并且需要 filter 它基于type财产 这本身工作得很好 但为了避免多余的类型声明 我想确保
  • 基于两列对数据框中的行进行求和[重复]

    这个问题在这里已经有答案了 我想添加一列的值 将它们按两列分组 我找到了如何在一列上执行此操作 但无法弄清楚如何在两列上执行此操作 例如 如果我有以下数据框 x c a a b b c c a a b b c c a a b b c c y
  • Spring Batch - 对数据列表中的每个项目重复步骤

    这是一项艰巨的任务 但我确信这并非闻所未闻 我有两个数据集 国家和人口统计数据 国家 地区数据集包含国家 地区名称及其人口统计数据的 ID 人口统计数据集是从乡村到郊区的分层数据集 这两个数据集都是每周从第三方获取的 我需要将人口统计数据分
  • 使用 Retrofit 2 添加标头以请求

    我正在尝试发送带有身份验证标头的请求 但服务器似乎无法识别客户端 我用了this https futurestud io tutorials android basic authentication with retrofit教程 并实现了
  • [重复]

    这个问题在这里已经有答案了 有什么区别List
  • Git 认为我每次进行小更改时都在重写我的一个文件

    我有一个中等大小的 Java 文件 每次我对一个文件 BuildTable java 进行更改时 Git 都会将其报告为巨大的更改 即使只是一两行 BuildTable java 大约有 200 行 本次提交中的更改仅更改了一行 git d
  • Flask-admin 内联建模传递表单参数会抛出 AttributeError

    Flask 开发者们大家好 在 Flask admin 中 我目前尝试在模型视图中实现内联模型编辑 在模型方面 我有一个简单的树结构 表示一组内容页面 每个节点都有多个子节点以及与其关联的多个内容数据模型 模型被命名为ContentNode
  • Android Facebook SDK 和 URL 方法成功形成好友对话框,但无法提交

    我开始认为这是一个错误 请证明我错了 我想以编程方式在 Facebook 上加好友 他们是唯一且肯定是该人在现实生活中认识的人 以下三种解决方案都具有相同的结果 成功的好友对话框 意味着个人资料名称 图片 指示操作的语句 与某人成为好友 以
  • Struts ActionForm 属性应该是什么类型?

    我使用 Struts 1 2 4 继承了这个巨大的遗留 Java Web 应用程序 我有一个关于 ActionForms 的具体问题 其中一些仅具有字符串属性 即使对于数字 其中一些使用看似合适的类型 整数 日期 字符串等 这里的最佳实践是
  • 使用 Docker 时未加载 Keycloak SPI 提供程序和层

    我正在尝试使用一些自定义内容 例如 logback 扩展 设置 docker 映像 因此我有一些 CLI 脚本 如下所示 subsystem logging remove extension org jboss as logging rem
  • 可扩展的宏定义

    灵感来自于评论区 https stackoverflow com questions 23879410 is it possible to extend a function lambda macro in scheme 23879575
  • JMS 规范或各种实现是否支持消息的传递确认?

    假设 Producer 向 JMS 主题 news 发送一条消息 Consumer1 读取了消息 但 Consumer2 离线 因此尚未读取消息 是否有任何内置 规范或实现 方式让生产者收到消费者 1 已读取其消息但消费者 2 尚未读取的通
  • 使用 PyQt 和 matplotlib 在可滚动小部件中显示多个绘图

    由于我没有得到答案this https stackoverflow com questions 12179893 creating a scrollable multiplot with pythons pylab我尝试用 PyQt 解决这
  • 如何高效生成总和在指定范围内的所有组合(在所有深度)

    假设您有一组值 1 1 1 12 12 16 如何生成总和在预定义范围内的所有可能组合 不重复 min max 例如 这里是 所有深度的 范围在13 and 17 1 12 1 1 12 1 1 1 12 16 1 16 这假设具有相同值的
  • Jupyter Notebook 找不到 IQSharp

    我一直在尝试为 Quantum Katas 运行 Q 但在找到 Q 内核方面遇到了一些困难 唯一显示的内核是用于 Jupyter Notebook 的 Python 3 内核 奇怪的是 当我执行 jupyter kernalspec lis
  • 使用 Rust 构建的 DLL 在运行时是否需要 libgcc.dll?

    如果我构建一个 DLLRust 语言 http rust lang org 是否需要libgcc dll在运行时出现 一方面 我在互联网上的某个地方看到过一个帖子 声称是的 rustc exe has libgcc s dw2 1 dll在
  • TypeScript 提供(未指定)泛型类型作为泛型参数

    我希望提供一个泛型类型作为类型参数无需先将其解析为具体类型 换句话说 我正在寻找一种方法来指定从基类继承时可以使用的类型映射函数 示例 不正确的 语法希望比我能解释得更好 abstract class RunIt