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

TypeScript中如何基于同实例字段收窄类型?

TypeScript 约束orgId与orgName的关联匹配问题

当前定义了Org类、orgs实例以及Data接口,但无法约束orgId和orgName的对应关系——当orgId为'ig'时,orgName填'Tiktok'不会触发报错,需要实现两者的强关联约束。

原代码如下:

class Org<Name extends string = string> {
    id: keyof typeof orgs; // 'tk' | 'ig'
    name: Name;
    
    constructor({id, name}) {
        this.id = id;
        this.name = name;
    }
}

const orgs = {
    tk: new Org({ id: 'tk', name: 'Tiktok' }),
    ig: new Org({ id: 'ig', name: 'Instagram' })
};

interface Data<
  A extends Org['id'] = Org['id']
> {
    orgId: A
    orgName: typeof orgs[A]['name'] 
}

const test1: Data = {
    orgId: 'ig',
    orgName: 'Instagram' // 正确
}

const test2: Data = {
    orgId: 'ig',
    orgName: 'Tiktok' // 应报错但未报错
}

解决方案

问题核心在于原Data接口的默认泛型参数会被推断为联合类型,导致orgName的类型变成所有可能名称的集合,无法实现强绑定。通过以下改动可解决:

class Org<Name extends string = string> {
    id: keyof typeof orgs;
    name: Name;
    
    constructor({id, name}: {id: keyof typeof orgs; name: Name}) {
        this.id = id;
        this.name = name;
    }
}

const orgs = {
    tk: new Org({ id: 'tk', name: 'Tiktok' }),
    ig: new Org({ id: 'ig', name: 'Instagram' })
} as const; // 锁定orgs的字面量类型,确保name为具体字符串值

// 生成orgId与orgName强绑定的联合类型
type Data = {
    [K in keyof typeof orgs]: {
        orgId: K;
        orgName: typeof orgs[K]['name'];
    }
}[keyof typeof orgs];

const test1: Data = {
    orgId: 'ig',
    orgName: 'Instagram' // 正确,无报错
}

const test2: Data = {
    orgId: 'ig',
    orgName: 'Tiktok' // 报错:类型 '"Tiktok"' 不能赋值给类型 '"Instagram"'
}

关键改动说明

  • orgs添加as const断言:将orgs的类型从宽泛的Org<string>实例集合,转换为只读的字面量类型集合,确保每个name的类型是具体的字符串字面量('Tiktok'/'Instagram'),而非通用string。
  • 重构Data为联合类型:通过映射类型遍历orgs的所有键,为每个键生成orgId与对应orgName的强绑定子类型,最后取所有子类型的联合,让Data成为{orgId: 'tk', orgName: 'Tiktok'} | {orgId: 'ig', orgName: 'Instagram'},自然约束两者的对应关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:09:58