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

TypeScript中如何修改泛型键对应的数组类型属性?

解决TypeScript泛型函数仅支持对象中string[]类型属性的类型推断问题

问题场景

需要编写一个泛型函数,仅允许操作对象中类型为string[](或其字面量数组子类型)的属性。示例类型如下:

const thing2 = ['!', '@', '#'] as const;
type Thing2 = typeof thing2[number];
const thing3 = ['1', '2', '3'] as const;
type Thing3 = typeof thing3[number];

type Thing = {
    a: Thing2[],
    b: Thing3[],
    c: number,
}

该函数仅应接受a和b作为键参数。

当前代码及问题

现有代码无法让TypeScript识别obj[key]为数组类型,报错Property 'push' does not exist on type 'O[K]',且希望尽量避免使用类型断言as:

type KeysMatching<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];

function append<O extends object, K extends KeysMatching<O, string[]>>(
    obj: O,
    key: K,
    item: O[K] extends (infer U)[] ? U : never
) {
    obj[key].push(item); // Property 'push' does not exist on type 'O[K]'
}

解决方案

问题核心是原约束仅限定了键的范围,未明确关联键对应值的数组类型。以下两种方案可解决该问题:

方案1:优化泛型约束,明确值类型关联

type KeysMatching<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never }[keyof T];

function append<O extends object, K extends KeysMatching<O, readonly string[]>>(
    obj: O & Record<K, string[]>, // 明确指定O[K]为数组类型
    key: K,
    item: O[K] extends (infer U)[] ? U : never
) {
    obj[key].push(item); // 类型推断正常
}

// 测试验证
const thing: Thing = { a: [], b: [], c: 1 };
append(thing, 'a', '!'); // 合法
append(thing, 'b', '1'); // 合法
// append(thing, 'c', 'x'); // 报错,符合预期

通过O & Record<K, string[]>给obj添加精确类型约束,让TypeScript明确obj[key]是带有push方法的数组类型。

方案2:内联约束,简化泛型逻辑

直接在泛型中约束O[K]为数组类型,省去KeysMatching的间接推导:

function append<O extends object, K extends keyof O>(
    obj: O,
    key: K extends (O[K] extends readonly string[] ? K : never),
    item: O[K] extends (infer U)[] ? U : never
) {
    obj[key].push(item);
}

// 测试验证
const thing: Thing = { a: [], b: [], c: 1 };
append(thing, 'a', '!');
append(thing, 'b', '1');
// append(thing, 'c', 'x'); // 报错,符合预期

这种方式将KeysMatching的逻辑内联到泛型约束中,缩短类型推断链条,让编译器直接识别obj[key]的数组属性。

原理说明

TypeScript泛型推断需要明确的类型关联,原代码仅限定了键的范围,未建立键与值类型的直接绑定。通过交叉类型或内联约束,我们让编译器明确知道K对应的O[K]是数组类型,从而正确识别push方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:40:08