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

TypeScript中如何向对象内的类型化数组推送元素?解决类型不兼容错误

解决TypeScript联合类型参数不匹配错误

错误信息

Argument of type 'Dogs | Cats | Fishs' is not assignable to parameter of type 'Dogs & Cats & Fishs'.
Type 'Dogs' is not assignable to type 'Dogs & Cats & Fishs'.
Property 'owner' is missing in type 'Dogs' but required in type 'Cats'.

原代码

interface Dogs {
    height: number,
    age: number,
    race: string,
    available: boolean,
}

interface Cats {
    height: number,
    age: number,
    owner: string
}

interface Fishs {
    weight: number,
    age: number,
    water: "sweet" | "salty"
}

interface Foo {
    animals: {
        dogs?: Dogs[],
        cats?: Cats[],
        fishs?: Fishs[] 
    }
}


type FooKeys = keyof Foo["animals"]
type FooState = Required<Foo>["animals"]
type FooStateTypes = Required<FooState>[keyof FooState][0]


const addAnimal = (fooState: FooState, animal: FooStateTypes, fooKey: keyof FooState) => {
    const fooStateAnimal = fooState[fooKey]
    if(fooStateAnimal) {
        fooStateAnimal.push(animal)
    } else {
        fooState[fooKey] = [animal]
    }
}

问题原因

当前函数中,fooKey和animal的类型是独立的联合类型,TypeScript无法确认传入的animal类型与fooKey对应的数组元素类型一致。它会假设fooState[fooKey]可能是Dogs[]、Cats[]或Fishs[]中的任意一种,因此要求animal必须同时满足三种类型的交集(Dogs & Cats & Fishs)才能安全推入所有可能的数组,这显然不符合实际需求。

解决方案

使用泛型绑定fooKey和animal的类型,让TypeScript明确两者的对应关系:

interface Dogs {
    height: number,
    age: number,
    race: string,
    available: boolean,
}

interface Cats {
    height: number,
    age: number,
    owner: string
}

interface Fishs {
    weight: number,
    age: number,
    water: "sweet" | "salty"
}

interface Foo {
    animals: {
        dogs?: Dogs[],
        cats?: Cats[],
        fishs?: Fishs[] 
    }
}


type FooKeys = keyof Foo["animals"]
type FooState = Required<Foo>["animals"]
type FooStateTypes = Required<FooState>[keyof FooState][0]


const addAnimal = <K extends keyof FooState>(
    fooState: FooState,
    animal: Required<FooState>[K][0],
    fooKey: K
) => {
    const fooStateAnimal = fooState[fooKey];
    if (fooStateAnimal) {
        fooStateAnimal.push(animal);
    } else {
        // 类型断言告知TypeScript当前赋值的数组类型与fooKey对应
        fooState[fooKey] = [animal] as Required<FooState>[K];
    }
}

关键说明

  • 泛型K约束为keyof FooState,限定fooKey只能是"dogs"、"cats"或"fishs"中的一个
  • animal的类型定义为Required<FooState>[K][0],直接关联到fooKey对应的数组元素类型,确保两者类型匹配
  • 赋值时的类型断言解决了可选属性赋值时的类型窄化问题

内容的提问来源于stack exchange,提问作者four-eyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:03:32