You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中实现类似Rust的泛型关联值访问?

Rust到TypeScript的泛型常量访问问题

示例Rust代码

trait Foo<F> {
    const FOO: F;
}

struct Bar;
impl Foo<u8> for Bar {
    const FOO: u8 = 1;
}

fn foo<T, F>() -> F
where
    T: Foo<F>,
{
    T::FOO
}

fn main() {
    println!("{}", foo::<Bar, _>()); // Prints: 1
}

这段Rust代码中,fn foo可通过泛型类型T直接访问关联常量FOO。现在希望在TypeScript中实现类似逻辑,但尝试的代码无法运行。

尝试的TypeScript代码(无法运行)

interface Foo<F> {
    foo: F;
}

class Bar {
    foo: 1 = 1;
}

function foo<T extends Foo<F>, F>(): F {
    return T.foo; // 'T' only refers to a type, but is being used as a value here.(2693)
}

console.log(foo<Bar, 1>());

可运行的TypeScript代码(需传入值)

interface Foo<F> {
    foo: F;
}

class Bar {
    foo: 1 = 1;
}

function foo<T extends Foo<F>, F>(foo_: T): F {
    return foo_.foo;
}

console.log(foo<Bar, 1>({foo: 1}));

具体问题

  • 是否有办法让function foo无需传入实际的T值就能访问T.foo,就像Rust代码中那样?即如何让函数读取传入的类型参数?注:已查阅过相关回答,但该方案不支持函数foo对类型T泛型化。
  • 知道TypeScript转译为JavaScript时会擦除所有类型信息,这也是return T.foo无法转译的原因。但转译器理应能推断:①任何T extends Foo<F>类型都有一个类型为F的foo字段;②任何Bar类型的值都必然有值恒为1的foo字段,符合Foo接口。基于这些信息,转译器在遇到foo<Bar, 1>()时应该能生成类似foo(Bar.foo)甚至foo(1)的代码。能否实现这种推断?若可以,如何操作?若不行,原因是什么?

回答

问题1:无需传值访问类型关联值的方案

TypeScript里无法直接通过类型参数访问值,因为类型在编译后会被完全擦除,运行时根本不存在T这个值。但可以通过类的静态属性绑定类型与值,模拟Rust的关联常量行为:

interface Foo<F> {
    readonly foo: F;
}

class Bar implements Foo<1> {
    // 用静态属性存储常量值
    static foo: 1 = 1;
    // 可选:实现接口的实例属性,保持类型对齐
    readonly foo: 1 = Bar.foo;
}

// 函数接收类的构造函数(值),而非仅类型参数
function foo<T extends { foo: F }, F>(ctor: T): F {
    return ctor.foo;
}

// 调用时传入类本身,TS会自动推断泛型
console.log(foo(Bar)); // 输出1

这种方式需要传入类的构造函数作为值,但已是最接近Rust关联常量逻辑的实现——因为TypeScript的类型系统和值系统是分离的,类型无法直接对应到值,必须通过构造函数这类“类型载体”建立关联。

问题2:能否让TS自动推断并生成传值代码?

不行,核心原因如下:

  1. 类型擦除的本质限制:TypeScript的类型检查与编译是独立阶段,类型检查的信息不会传递到JS代码生成阶段。类型参数编译后完全消失,运行时函数根本不知道你指定了Bar这个类型,自然无法自动插入对应的值。
  2. 类型与值的分离设计:TypeScript的类型系统仅用于静态检查,不会修改运行时的代码结构。即使能推断出Bar.foo的值是1,也不会主动将这个值注入函数调用——这会打破“类型不影响运行时”的设计原则。
  3. 泛型的通用性限制:foo是泛型函数,要支持所有符合Foo<F>的类型。编译器无法提前预知你会传入哪个具体类型,也就无法提前生成对应的值代码。TypeScript不会像Rust那样对泛型函数做单态化处理,只能编译成通用的JS代码。

总结来说,TypeScript的设计目标是作为JavaScript的超集,保留JS的运行时特性,因此不会像Rust那样让类型直接关联运行时值,也不会根据类型推断修改运行时代码结构。

内容的提问来源于stack exchange,提问作者shniubobo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 16:12:29