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

TypeScript映射类型中数组类型扁平化转换失败问题

问题:将嵌套对象与数组属性统一转为number类型的映射类型错误

原始接口定义

interface IUserMongo {
  name: string;
  age: number;
  address: string[];
  nested: {
    name: string;
    sayYes: boolean;
    rrr: 1;
  };
}

期望生成的类型

希望派生一个所有属性(包括嵌套对象属性)类型均为number的类型:

interface IUserMongo {
  name: number;
  age: number;
  address: number;
  nested: {
    name: number;
    sayYes: number;
    rrr: number;
  };
}

当前问题

编写的IUserProject映射类型处理嵌套对象正常,但处理数组时触发类型错误:

error: Type 'number' is not assignable to type 'number[]'

完整代码示例

interface IUserMongo {
  name: string;
  age: number;
  address: string[];
  nested: {
    name: string;
    sayYes: boolean;
    rrr: 1;
  };
}

type IUserProject<T, N = number> = {
  [K in keyof T]: T[K] extends object ? IUserProject<T[K], N> : N;
};

const projection: IUserProject<IUserMongo> = {
  name: 1,
  age: 1,
  address: 1, // 此处报错
  nested: {
    sayYes: 1,
    name: 1,
    rrr: 1,
  },
};

const user: IUserMongo = {
  name: 'sdg',
  age: 1,
  address: ['gfg'],
  nested: {
    sayYes: true,
    name: 'rrr',
    rrr: 1,
  },
};

// 期望的数组处理行为示例
interface MultiContainer {
  Item1: string[];
  Item2: number[];
}

type SingleContainer = { [P in keyof MultiContainer]: number };

const tt: SingleContainer = {
    Item1: 1,
    Item2: 1,
};

问题原因

当前的映射类型中,T[K] extends object会将数组判定为object类型(数组在TypeScript中属于object的子类型),导致代码递归处理数组的元素类型,最终数组属性被映射为number[],但我们需要的是直接将数组属性的类型替换为number。

解决方案

修改映射类型,优先判断属性是否为数组类型,若是则直接返回目标类型N;否则再判断是否为对象并递归处理:

type IUserProject<T, N = number> = {
  [K in keyof T]: T[K] extends readonly any[] ? N : 
    T[K] extends object ? IUserProject<T[K], N> : N;
};

修改后,projection中的address:1不再报错,所有属性类型均符合期望的number类型,包括嵌套对象的属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:50:29