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

如何在TypeScript中将类型映射到对象实例类型?

解决方案

要实现根据实例类型约束第二个参数的类型,核心是让TypeScript能够准确区分不同的类实例类型,结合类型映射来关联实例与目标类型。以下是两种可行方案:

方案一:添加唯一标识属性(Tag)

由于TypeScript是结构类型系统,仅靠方法返回值无法区分结构相似的类。我们可以给每个子类添加一个只读的唯一标识属性,让TypeScript能识别它们的差异:

class Buzz{
    name: string

    constructor(name: string) {
        this.name = name;
    }

    greet() {
        console.log(`Hi, I'm ${this.name}`)
    }

    getTitle():string {
        return `Senior commander ${this.name}`
    }
}

class Foo extends Buzz{
    readonly type = 'Foo' as const; // 添加唯一标识
    constructor(name: string) {
        super(name);
    }

    getTitle():string {
        return `Professor ${this.name} the Fourth`
    }
}

class Bar extends Buzz{
    readonly type = 'Bar' as const; // 添加唯一标识
    constructor(name: string) {
        super(name);
    }

    getTitle():string {
        return `${this.name} the one and only.`
    }
}

// 定义实例类型到目标值的映射
type InstanceToValue = {
    Foo: 'Foo';
    Bar: 'Bar';
}

// 利用标识属性做类型约束
function fooBarObj<T extends Foo | Bar>(s: T, t: InstanceToValue[T['type']]){};

// 验证调用
fooBarObj(new Foo('foo'), 'Foo') // ✅ 正确
fooBarObj(new Bar('bar'), 'Bar') // ✅ 正确
fooBarObj(new Foo('foo'), 'Bar') // ❌ 类型错误

方案二:利用构造函数类型映射

不需要修改类结构,直接通过实例的构造函数类型来做映射:

class Buzz{
    name: string

    constructor(name: string) {
        this.name = name;
    }

    greet() {
        console.log(`Hi, I'm ${this.name}`)
    }

    getTitle():string {
        return `Senior commander ${this.name}`
    }
}

class Foo extends Buzz{
    constructor(name: string) {
        super(name);
    }

    getTitle():string {
        return `Professor ${this.name} the Fourth`
    }
}

class Bar extends Buzz{
    constructor(name: string) {
        super(name);
    }

    getTitle():string {
        return `${this.name} the one and only.`
    }
}

// 定义构造函数到目标值的映射
type ConstructorToValue = {
    [K in typeof Foo]: 'Foo';
    [K in typeof Bar]: 'Bar';
}

// 通过实例的构造函数类型约束参数
function fooBarObj<T extends Foo | Bar>(s: T, t: ConstructorToValue[typeof s]){};

// 验证调用
fooBarObj(new Foo('foo'), 'Foo') // ✅ 正确
fooBarObj(new Bar('bar'), 'Bar') // ✅ 正确
fooBarObj(new Bar('bar'), 'Foo') // ❌ 类型错误

原理说明

  • 方案一通过添加readonly type属性,给每个子类实例赋予了唯一的字面量类型,让TypeScript能精准区分不同实例类型,再通过索引访问映射类型得到对应的约束值。
  • 方案二利用typeof 实例会返回其构造函数类型的特性,通过构造函数类型与目标值的映射,实现参数类型的关联约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 07:32:17